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

Andriy Voskoboinyk avos at FreeBSD.org
Sun Dec 13 21:50:39 UTC 2015


Author: avos
Date: Sun Dec 13 21:50:38 2015
New Revision: 292174
URL: https://svnweb.freebsd.org/changeset/base/292174

Log:
  urtwn: add a command queue for sleepable tasks.
  
  An implementation from rum(4) was used (it looks simpler for me).
  Will be used for h/w encryption support.
  
  Reviewed by:	kevlo
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D4447

Modified:
  head/sys/dev/usb/wlan/if_urtwn.c
  head/sys/dev/usb/wlan/if_urtwnvar.h

Modified: head/sys/dev/usb/wlan/if_urtwn.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c	Sun Dec 13 21:43:54 2015	(r292173)
+++ head/sys/dev/usb/wlan/if_urtwn.c	Sun Dec 13 21:50:38 2015	(r292174)
@@ -213,6 +213,9 @@ static uint16_t		urtwn_read_2(struct urt
 static uint32_t		urtwn_read_4(struct urtwn_softc *, uint16_t);
 static int		urtwn_fw_cmd(struct urtwn_softc *, uint8_t,
 			    const void *, int);
+static void		urtwn_cmdq_cb(void *, int);
+static int		urtwn_cmd_sleepable(struct urtwn_softc *, const void *,
+			    size_t, CMD_FUNC_PROTO);
 static void		urtwn_r92c_rf_write(struct urtwn_softc *, int,
 			    uint8_t, uint32_t);
 static void		urtwn_r88e_rf_write(struct urtwn_softc *, int,
@@ -427,6 +430,7 @@ urtwn_attach(device_t self)
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(self),
 	    MTX_NETWORK_LOCK, MTX_DEF);
+	URTWN_CMDQ_LOCK_INIT(sc);
 	URTWN_NT_LOCK_INIT(sc);
 	callout_init(&sc->sc_watchdog_ch, 0);
 	mbufq_init(&sc->sc_snd, ifqmaxlen);
@@ -525,6 +529,8 @@ urtwn_attach(device_t self)
 	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
 	    URTWN_RX_RADIOTAP_PRESENT);
 
+	TASK_INIT(&sc->cmdq_task, 0, urtwn_cmdq_cb, sc);
+
 	if (bootverbose)
 		ieee80211_announce(ic);
 
@@ -574,8 +580,13 @@ urtwn_detach(device_t self)
 	urtwn_free_rx_list(sc);
 	URTWN_UNLOCK(sc);
 
-	ieee80211_ifdetach(ic);
+	if (ic->ic_softc == sc) {
+		ieee80211_draintask(ic, &sc->cmdq_task);
+		ieee80211_ifdetach(ic);
+	}
+
 	URTWN_NT_LOCK_DESTROY(sc);
+	URTWN_CMDQ_LOCK_DESTROY(sc);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -1259,6 +1270,64 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uin
 	return (0);
 }
 
+static void
+urtwn_cmdq_cb(void *arg, int pending)
+{
+	struct urtwn_softc *sc = arg;
+	struct urtwn_cmdq *item;
+
+	/*
+	 * Device must be powered on (via urtwn_power_on())
+	 * before any command may be sent.
+	 */
+	URTWN_LOCK(sc);
+	if (!(sc->sc_flags & URTWN_RUNNING)) {
+		URTWN_UNLOCK(sc);
+		return;
+	}
+
+	URTWN_CMDQ_LOCK(sc);
+	while (sc->cmdq[sc->cmdq_first].func != NULL) {
+		item = &sc->cmdq[sc->cmdq_first];
+		sc->cmdq_first = (sc->cmdq_first + 1) % URTWN_CMDQ_SIZE;
+		URTWN_CMDQ_UNLOCK(sc);
+
+		item->func(sc, &item->data);
+
+		URTWN_CMDQ_LOCK(sc);
+		memset(item, 0, sizeof (*item));
+	}
+	URTWN_CMDQ_UNLOCK(sc);
+	URTWN_UNLOCK(sc);
+}
+
+static int
+urtwn_cmd_sleepable(struct urtwn_softc *sc, const void *ptr, size_t len,
+    CMD_FUNC_PROTO)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+
+	KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
+
+	URTWN_CMDQ_LOCK(sc);
+	if (sc->cmdq[sc->cmdq_last].func != NULL) {
+		device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
+		URTWN_CMDQ_UNLOCK(sc);
+
+		return (EAGAIN);
+	}
+
+	if (ptr != NULL)
+		memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
+	sc->cmdq[sc->cmdq_last].func = func;
+	sc->cmdq_last = (sc->cmdq_last + 1) % URTWN_CMDQ_SIZE;
+	URTWN_CMDQ_UNLOCK(sc);
+
+	ieee80211_runtask(ic, &sc->cmdq_task);
+
+	return (0);
+}
+
 static __inline void
 urtwn_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
 {

Modified: head/sys/dev/usb/wlan/if_urtwnvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnvar.h	Sun Dec 13 21:43:54 2015	(r292173)
+++ head/sys/dev/usb/wlan/if_urtwnvar.h	Sun Dec 13 21:50:38 2015	(r292174)
@@ -71,15 +71,18 @@ struct urtwn_data {
 };
 typedef STAILQ_HEAD(, urtwn_data) urtwn_datahead;
 
+union sec_param {
+	struct ieee80211_key		key;
+};
+
+#define CMD_FUNC_PROTO			void (*func)(struct urtwn_softc *, \
+					    union sec_param *)
+
 struct urtwn_cmdq {
-	void			*arg0;
-	void			*arg1;
-	void			(*func)(void *);
-	struct ieee80211_key	*k;
-	struct ieee80211_key	key;
-	uint8_t			mac[IEEE80211_ADDR_LEN];
-	uint8_t			wcid;
+	union sec_param			data;
+	CMD_FUNC_PROTO;
 };
+#define URTWN_CMDQ_SIZE			16
 
 struct urtwn_fw_info {
 	const uint8_t		*data;
@@ -203,17 +206,11 @@ struct urtwn_softc {
 	struct callout			sc_watchdog_ch;
 	struct mtx			sc_mtx;
 
-/* need to be power of 2, otherwise URTWN_CMDQ_GET fails */
-#define	URTWN_CMDQ_MAX	16
-#define	URTWN_CMDQ_MASQ	(URTWN_CMDQ_MAX - 1)
-	struct urtwn_cmdq		cmdq[URTWN_CMDQ_MAX];
+	struct urtwn_cmdq		cmdq[URTWN_CMDQ_SIZE];
+	struct mtx			cmdq_mtx;
 	struct task			cmdq_task;
-	uint32_t			cmdq_store;
-	uint8_t                         cmdq_exec;
-	uint8_t                         cmdq_run;
-	uint8_t                         cmdq_key_set;
-#define	URTWN_CMDQ_ABORT	0
-#define	URTWN_CMDQ_GO		1
+	uint8_t				cmdq_first;
+	uint8_t				cmdq_last;
 
 	uint32_t			rf_chnlbw[R92C_MAX_CHAINS];
 	struct usb_xfer			*sc_xfer[URTWN_N_TRANSFER];
@@ -226,6 +223,12 @@ struct urtwn_softc {
 #define	URTWN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
 #define	URTWN_ASSERT_LOCKED(sc)		mtx_assert(&(sc)->sc_mtx, MA_OWNED)
 
+#define URTWN_CMDQ_LOCK_INIT(sc) \
+	mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
+#define URTWN_CMDQ_LOCK(sc)		mtx_lock(&(sc)->cmdq_mtx)
+#define URTWN_CMDQ_UNLOCK(sc)		mtx_unlock(&(sc)->cmdq_mtx)
+#define URTWN_CMDQ_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->cmdq_mtx)
+
 #define URTWN_NT_LOCK_INIT(sc) \
 	mtx_init(&(sc)->nt_mtx, "node table lock", NULL, MTX_DEF)
 #define URTWN_NT_LOCK(sc)		mtx_lock(&(sc)->nt_mtx)


More information about the svn-src-head mailing list