PERFORCE change 181189 for review

Hans Petter Selasky hselasky at FreeBSD.org
Mon Jul 19 19:18:34 UTC 2010


http://p4web.freebsd.org/@@181189?ac=10

Change 181189 by hselasky at hselasky_laptop001 on 2010/07/19 19:17:47

	
	USB WLAN (RUN-driver update):
		* Because hostapd calls iv_key_set() before if_init(), made sure key_set callback function
		will be executed, and the key won't be deleted during init process.
		* txmic and rxmic are written into the chip the same place regardless of opmode.
		* Made hardware generate 802.11 sequence numbers.
		* make command queuing atomic by adding another mutex
		* some minor whitespace/tab styling
		* remove errornous semicolon.
	
		- patch by Akinori
	
	Reviewed by:	hselasky @

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#15 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_runvar.h#9 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#15 (text+ko) ====

@@ -90,12 +90,6 @@
 #define IEEE80211_HAS_ADDR4(wh) \
 	(((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
 
-/*
- * Because of LOR in run_key_delete(), use atomic instead.
- * '& RUN_CMDQ_MASQ' is to loop cmdq[].
- */
-#define RUN_CMDQ_GET(c)	(atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
-
 static const struct usb_device_id run_devs[] = {
     { USB_VP(USB_VENDOR_ABOCOM,		USB_PRODUCT_ABOCOM_RT2770) },
     { USB_VP(USB_VENDOR_ABOCOM,		USB_PRODUCT_ABOCOM_RT2870) },
@@ -554,6 +548,8 @@
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
 	    MTX_NETWORK_LOCK, MTX_DEF);
+	mtx_init(&sc->sc_cmdq_mtx, device_get_nameunit(sc->sc_dev),
+	    MTX_NETWORK_LOCK, MTX_DEF);
 
 	iface_index = RT2860_IFACE_INDEX;
 
@@ -719,7 +715,10 @@
 	RUN_LOCK(sc);
 
 	sc->ratectl_run = RUN_RATECTL_OFF;
+
+	RUN_CMDQ_LOCK(sc);
 	sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT;
+	RUN_CMDQ_UNLOCK(sc);
 
 	/* free TX list, if any */
 	for (i = 0; i != RUN_EP_QUEUES; i++)
@@ -737,6 +736,7 @@
 	}
 
 	mtx_destroy(&sc->sc_mtx);
+	mtx_destroy(&sc->sc_cmdq_mtx);
 
 	return (0);
 }
@@ -830,9 +830,6 @@
 	if(sc->rvp_cnt++ == 0)
 		ic->ic_opmode = opmode;
 
-	if(opmode == IEEE80211_M_HOSTAP)
-		sc->cmdq_run = RUN_CMDQ_GO;
-
 	DPRINTF("rvp_id=%d bmap=%x rvp_cnt=%d\n",
 	    rvp->rvp_id, sc->rvp_bmap, sc->rvp_cnt);
 
@@ -889,27 +886,53 @@
 	struct run_softc *sc = arg;
 	uint8_t i;
 
-	/* call cmdq[].func locked */
-	RUN_LOCK(sc);
-	for(i = sc->cmdq_exec; sc->cmdq[i].func && pending;
-	    i = sc->cmdq_exec, pending--){
+	RUN_CMDQ_LOCK(sc);
+	for (i = sc->cmdq_exec; sc->cmdq[i].func; i = sc->cmdq_exec){
 		DPRINTFN(6, "cmdq_exec=%d pending=%d\n", i, pending);
-		if(sc->cmdq_run == RUN_CMDQ_GO){
+		if ((sc->cmdq_run == RUN_CMDQ_GO) ||
+		    ((sc->cmdq_key_set == RUN_CMDQ_GO) &&
+		    (sc->cmdq[i].func == run_key_set_cb))) {
+			RUN_CMDQ_UNLOCK(sc);
+			RUN_LOCK(sc);
 			/*
 			 * If arg0 is NULL, callback func needs more
 			 * than one arg. So, pass ptr to cmdq struct.
 			 */
-			if(sc->cmdq[i].arg0)
+			if (sc->cmdq[i].arg0)
 				sc->cmdq[i].func(sc->cmdq[i].arg0);
 			else
 				sc->cmdq[i].func(&sc->cmdq[i]);
+			RUN_UNLOCK(sc);
+			RUN_CMDQ_LOCK(sc);
 		}
 		sc->cmdq[i].arg0 = NULL;
 		sc->cmdq[i].func = NULL;
 		sc->cmdq_exec++;
 		sc->cmdq_exec &= RUN_CMDQ_MASQ;
 	}
-	RUN_UNLOCK(sc);
+	RUN_CMDQ_UNLOCK(sc);
+}
+
+static uint8_t
+run_cmdq_append(struct run_softc *sc)
+{
+	uint8_t i;
+
+	RUN_CMDQ_LOCK_ASSERT(sc, MA_OWNED);
+
+	i = sc->cmdq_store;
+
+	DPRINTF("cmdq_store=%d\n", i);
+
+	if (sc->cmdq[i].func != NULL) {
+		DPRINTF("cmdq is full\n");
+		return (RUN_CMDQ_MAX);
+	}
+
+	sc->cmdq_store++;
+	sc->cmdq_store &= RUN_CMDQ_MASQ;
+
+	return (i);
 }
 
 static void
@@ -1771,6 +1794,19 @@
 	case IEEE80211_S_INIT:
 		restart_ratectl = 1;
 
+		/*
+		 * When hostapd has set a key, don't clear it. But,
+		 * when the device is being brought down, clear it.
+		 */
+		if ((sc->cmdq_key_set != RUN_CMDQ_GO) ||
+		    (ostate == IEEE80211_S_RUN)) {
+			/* clear shared key table */
+			run_set_region_4(sc,
+			    RT2860_SKEY(rvp->rvp_id, 0), 0, 4 * 32);
+			/* clear shared key mode */
+			run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4);
+		}
+
 		if (ostate != IEEE80211_S_RUN)
 			break;
 
@@ -1921,12 +1957,20 @@
 {
 	struct run_softc *sc = ic->ic_ifp->if_softc;
 
-	/* sometime called wothout lock */
-	if(mtx_owned(&ic->ic_comlock.mtx)){
-		uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store);
-		DPRINTF("cmdq_store=%d\n", i);
+	/* sometime called without lock */
+	if (mtx_owned(&ic->ic_comlock.mtx)){
+		uint8_t i;
+
+		RUN_CMDQ_LOCK(sc);
+		i = run_cmdq_append(sc);
+		if (i >= RUN_CMDQ_MAX) {
+			RUN_CMDQ_UNLOCK(sc);
+			return (-1);
+		}
 		sc->cmdq[i].func = run_wme_update_cb;
 		sc->cmdq[i].arg0 = ic;
+		RUN_CMDQ_UNLOCK(sc);
+
 		ieee80211_runtask(ic, &sc->cmdq_task);
 		return (0);
 	}
@@ -1970,7 +2014,7 @@
 
 	RUN_LOCK_ASSERT(sc, MA_OWNED);
 
-	if(vap->iv_opmode == IEEE80211_M_HOSTAP)
+	if (vap->iv_opmode == IEEE80211_M_HOSTAP)
 		ni = ieee80211_find_vap_node(&ic->ic_sta, vap, cmdq->mac);
 	else
 		ni = vap->iv_bss;
@@ -2085,28 +2129,32 @@
 {
 	struct ieee80211com *ic = vap->iv_ic;
 	struct run_softc *sc = ic->ic_ifp->if_softc;
-	uint32_t i;
+	uint8_t i;
 
-	i = RUN_CMDQ_GET(&sc->cmdq_store);
-	DPRINTF("cmdq_store=%d\n", i);
+	RUN_CMDQ_LOCK(sc);
+	i = run_cmdq_append(sc);
+	if (i >= RUN_CMDQ_MAX) {
+		RUN_CMDQ_UNLOCK(sc);
+		return (0);
+	}
 	sc->cmdq[i].func = run_key_set_cb;
 	sc->cmdq[i].arg0 = NULL;
 	sc->cmdq[i].arg1 = vap;
 	sc->cmdq[i].k = k;
 	IEEE80211_ADDR_COPY(sc->cmdq[i].mac, mac);
-	ieee80211_runtask(ic, &sc->cmdq_task);
 
 	/*
-	 * To make sure key will be set when hostapd
-	 * calls iv_key_set() before if_init().
+	 * To make sure key will be set when hostapd calls
+	 * iv_key_set() before if_init().
 	 */
-	if(vap->iv_opmode == IEEE80211_M_HOSTAP){
-		RUN_LOCK(sc);
+	if (vap->iv_opmode == IEEE80211_M_HOSTAP)
 		sc->cmdq_key_set = RUN_CMDQ_GO;
-		RUN_UNLOCK(sc);
-	}
+
+	RUN_CMDQ_UNLOCK(sc);
+
+	ieee80211_runtask(ic, &sc->cmdq_task);
 
-	return(1);
+	return (1);
 }
 
 /*
@@ -2154,16 +2202,18 @@
 	struct ieee80211com *ic = vap->iv_ic;
 	struct run_softc *sc = ic->ic_ifp->if_softc;
 	struct ieee80211_key *k0;
-	uint32_t i;
+	uint8_t i;
 
 	/*
 	 * When called back, key might be gone. So, make a copy
 	 * of some values need to delete keys before deferring.
-	 * But, because of LOR with node lock, cannot use lock here.
-	 * So, use atomic instead.
 	 */
-	i = RUN_CMDQ_GET(&sc->cmdq_store);
-	DPRINTF("cmdq_store=%d\n", i);
+	RUN_CMDQ_LOCK(sc);
+	i = run_cmdq_append(sc);
+	if (i >= RUN_CMDQ_MAX) {
+		RUN_CMDQ_UNLOCK(sc);
+		return (0);
+	}
 	sc->cmdq[i].func = run_key_delete_cb;
 	sc->cmdq[i].arg0 = NULL;
 	sc->cmdq[i].arg1 = sc;
@@ -2172,9 +2222,11 @@
 	k0->wk_keyix = k->wk_keyix;
 	/* matching wcid was written to wk_pad in run_key_set() */
 	k0->wk_pad = k->wk_pad;
+	RUN_CMDQ_UNLOCK(sc);
+
 	ieee80211_runtask(ic, &sc->cmdq_task);
+
 	return (1);	/* return fake success */
-
 }
 
 static void
@@ -2362,18 +2414,25 @@
 	}
 
 	/* only interested in true associations */
-	if (isnew && ni->ni_associd != 0){
-
+	if (isnew && ni->ni_associd != 0) {
 		/*
-		 * This function could is called though timeout function.
-		 * Need to defer.
+		 * This function could be called through timeout
+		 * callback. Need to defer.
 		 */
-		uint32_t cnt = RUN_CMDQ_GET(&sc->cmdq_store);
-		DPRINTF("cmdq_store=%d\n", cnt);
+		uint8_t cnt;
+
+		RUN_CMDQ_LOCK(sc);
+		cnt = run_cmdq_append(sc);
+		if (cnt >= RUN_CMDQ_MAX) {
+			RUN_CMDQ_UNLOCK(sc);
+			return;
+		}
 		sc->cmdq[cnt].func = run_newassoc_cb;
 		sc->cmdq[cnt].arg0 = NULL;
 		sc->cmdq[cnt].arg1 = ni;
 		sc->cmdq[cnt].wcid = wcid;
+		RUN_CMDQ_UNLOCK(sc);
+
 		ieee80211_runtask(ic, &sc->cmdq_task);
 	}
 
@@ -2803,13 +2862,18 @@
 			vap = TAILQ_FIRST(&ic->ic_vaps);
 
 		if (error != USB_ERR_CANCELLED) {
-			if (error == USB_ERR_TIMEOUT) {
+			if ((error == USB_ERR_TIMEOUT) && (vap != NULL)) {
+				uint8_t i;
 				device_printf(sc->sc_dev, "device timeout\n");
-				uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store);
-				DPRINTF("cmdq_store=%d\n", i);
-				sc->cmdq[i].func = run_usb_timeout_cb;
-				sc->cmdq[i].arg0 = vap;
-				ieee80211_runtask(ic, &sc->cmdq_task);
+				RUN_CMDQ_LOCK(sc);
+				i = run_cmdq_append(sc);
+				if (i < RUN_CMDQ_MAX) {
+					sc->cmdq[i].func = run_usb_timeout_cb;
+					sc->cmdq[i].arg0 = vap;
+				}
+				RUN_CMDQ_UNLOCK(sc);
+				if (i < RUN_CMDQ_MAX)
+					ieee80211_runtask(ic, &sc->cmdq_task);
 			}
 
 			/*
@@ -3064,14 +3128,22 @@
 		 */
 		if(sc->fifo_cnt++ == 10){
 			/*
-			 * With multiple vaps or if_bridge, if_start() is called
-			 * with a non-sleepable lock, tcpinp. So, need to defer.
+			 * With multiple vaps or if_bridge, if_start()
+			 * is called with a non-sleepable lock,
+			 * tcpinp. So, need to defer.
 			 */
-			uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store);
-			DPRINTFN(6, "cmdq_store=%d\n", i);
-			sc->cmdq[i].func = run_drain_fifo;
-			sc->cmdq[i].arg0 = sc;
-			ieee80211_runtask(ic, &sc->cmdq_task);
+			uint8_t i;
+
+			RUN_CMDQ_LOCK(sc);
+			i = run_cmdq_append(sc);
+			if (i < RUN_CMDQ_MAX) {
+				sc->cmdq[i].func = run_drain_fifo;
+				sc->cmdq[i].arg0 = sc;
+			}
+			RUN_CMDQ_UNLOCK(sc);
+			if (i < RUN_CMDQ_MAX)
+				ieee80211_runtask(ic, &sc->cmdq_task);
+
 		}
 	}
 
@@ -3188,7 +3260,7 @@
 	ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
 
 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
-	dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort);
+	dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
 	    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
 	wflags = RT2860_TX_FRAG;
 
@@ -3906,15 +3978,18 @@
 {
 	struct ieee80211com *ic = vap->iv_ic;
 	struct run_softc *sc = ic->ic_ifp->if_softc;
-	uint32_t i;
+	uint8_t i;
 
-	i = RUN_CMDQ_GET(&sc->cmdq_store);
-	DPRINTF("cmdq_store=%d\n", i);
-	sc->cmdq[i].func = run_update_beacon_cb;
-	sc->cmdq[i].arg0 = vap;
-	ieee80211_runtask(ic, &sc->cmdq_task);
+	RUN_CMDQ_LOCK(sc);
+	i = run_cmdq_append(sc);
+	if (i < RUN_CMDQ_MAX) {
+		sc->cmdq[i].func = run_update_beacon_cb;
+		sc->cmdq[i].arg0 = vap;
+	}
+	RUN_CMDQ_UNLOCK(sc);
+	if (i < RUN_CMDQ_MAX)
+		ieee80211_runtask(ic, &sc->cmdq_task);
 
-	return;
 }
 
 static void
@@ -4693,14 +4768,6 @@
 	/* clear WCID attribute table */
 	run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32);
 
-	/* hostapd sets a key before init. So, don't clear it. */
-	if(sc->cmdq_key_set != RUN_CMDQ_GO){
-		/* clear shared key table */
-		run_set_region_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32);
-		/* clear shared key mode */
-		run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4);
-	}
-
 	run_read(sc, RT2860_US_CYC_CNT, &tmp);
 	tmp = (tmp & ~0xff) | 0x1e;
 	run_write(sc, RT2860_US_CYC_CNT, tmp);
@@ -4759,7 +4826,10 @@
 
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+	RUN_CMDQ_LOCK(sc);
 	sc->cmdq_run = RUN_CMDQ_GO;
+	RUN_CMDQ_UNLOCK(sc);
 
 	for(i = 0; i != RUN_N_XFER; i++)
 		usbd_xfer_set_stall(sc->sc_xfer[i]);
@@ -4807,7 +4877,10 @@
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
 	sc->ratectl_run = RUN_RATECTL_OFF;
-	sc->cmdq_run = sc->cmdq_key_set;
+
+	RUN_CMDQ_LOCK(sc);
+	sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT;
+	RUN_CMDQ_UNLOCK(sc);
 
 	RUN_UNLOCK(sc);
 

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_runvar.h#9 (text+ko) ====

@@ -23,7 +23,7 @@
 #ifndef _IF_RUNVAR_H_
 #define	_IF_RUNVAR_H_
 
-#define RUN_MAX_RXSZ			\
+#define	RUN_MAX_RXSZ			\
 	MIN(4096, MJUMPAGESIZE)
 #if 0
 	(sizeof (uint32_t) +		\
@@ -33,21 +33,21 @@
 	 sizeof (struct rt2870_rxd))
 #endif
 /* NB: "11" is the maximum number of padding bytes needed for Tx */
-#define RUN_MAX_TXSZ			\
+#define	RUN_MAX_TXSZ			\
 	(sizeof (struct rt2870_txd) +	\
 	 sizeof (struct rt2860_rxwi) +	\
 	 MCLBYTES + 11)
 
-#define RUN_TX_TIMEOUT	5000	/* ms */
+#define	RUN_TX_TIMEOUT	5000	/* ms */
 
 /* Tx ring count was 8/endpoint, now 32 for all 4 (or 6) endpoints. */
-#define RUN_TX_RING_COUNT	32
-#define RUN_RX_RING_COUNT	1
+#define	RUN_TX_RING_COUNT	32
+#define	RUN_RX_RING_COUNT	1
 
-#define RT2870_WCID_MAX		64
-#define RUN_AID2WCID(aid)	((aid) & 0xff)
+#define	RT2870_WCID_MAX		64
+#define	RUN_AID2WCID(aid)	((aid) & 0xff)
 
-#define RUN_VAP_MAX		8
+#define	RUN_VAP_MAX		8
 
 struct run_rx_radiotap_header {
 	struct ieee80211_radiotap_header wr_ihdr;
@@ -60,7 +60,7 @@
 	uint8_t		wr_antsignal;
 } __packed;
 
-#define RUN_RX_RADIOTAP_PRESENT				\
+#define	RUN_RX_RADIOTAP_PRESENT				\
 	(1 << IEEE80211_RADIOTAP_FLAGS |		\
 	 1 << IEEE80211_RADIOTAP_RATE |			\
 	 1 << IEEE80211_RADIOTAP_CHANNEL |		\
@@ -77,9 +77,9 @@
 	uint8_t		wt_hwqueue;
 } __packed;
 
-#define IEEE80211_RADIOTAP_HWQUEUE 15
+#define	IEEE80211_RADIOTAP_HWQUEUE 15
 
-#define RUN_TX_RADIOTAP_PRESENT				\
+#define	RUN_TX_RADIOTAP_PRESENT				\
 	(1 << IEEE80211_RADIOTAP_FLAGS |		\
 	 1 << IEEE80211_RADIOTAP_RATE |			\
 	 1 << IEEE80211_RADIOTAP_CHANNEL |		\
@@ -127,7 +127,7 @@
 
 	uint8_t				rvp_id;
 };
-#define RUN_VAP(vap)    ((struct run_vap *)(vap))
+#define	RUN_VAP(vap)    ((struct run_vap *)(vap))
 
 /*
  * There are 7 bulk endpoints: 1 for RX
@@ -202,25 +202,26 @@
 	uint8_t				sc_bssid[6];
 
 	struct mtx			sc_mtx;
+	struct mtx			sc_cmdq_mtx;
 
 	struct run_endpoint_queue	sc_epq[RUN_EP_QUEUES];
 
 	struct task                     ratectl_task;
 	struct usb_callout              ratectl_ch;
 	uint8_t				ratectl_run;
-#define RUN_RATECTL_OFF	0
+#define	RUN_RATECTL_OFF	0
 
-/* need to be power of 2, otherwise RUN_CMDQ_GET fails */
-#define RUN_CMDQ_MAX	16
-#define RUN_CMDQ_MASQ	(RUN_CMDQ_MAX - 1)
+/* need to be power of 2, otherwise modulo assumptions fail */
+#define	RUN_CMDQ_MAX	16
+#define	RUN_CMDQ_MASQ	(RUN_CMDQ_MAX - 1)
 	struct run_cmdq			cmdq[RUN_CMDQ_MAX];
 	struct task			cmdq_task;
-	uint32_t			cmdq_store;
+	uint8_t				cmdq_store;
 	uint8_t				cmdq_exec;
 	uint8_t				cmdq_run;
 	uint8_t				cmdq_key_set;
-#define RUN_CMDQ_ABORT	0
-#define RUN_CMDQ_GO	1
+#define	RUN_CMDQ_ABORT	0
+#define	RUN_CMDQ_GO	1
 
 	struct usb_xfer			*sc_xfer[RUN_N_XFER];
 
@@ -240,19 +241,23 @@
 		struct run_rx_radiotap_header th;
 		uint8_t	pad[64];
 	}				sc_rxtapu;
-#define sc_rxtap	sc_rxtapu.th
+#define	sc_rxtap	sc_rxtapu.th
 	int				sc_rxtap_len;
 
 	union {
 		struct run_tx_radiotap_header th;
 		uint8_t	pad[64];
 	}				sc_txtapu;
-#define sc_txtap	sc_txtapu.th
+#define	sc_txtap	sc_txtapu.th
 	int				sc_txtap_len;
 };
 
-#define RUN_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
-#define RUN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
-#define RUN_LOCK_ASSERT(sc, t)	mtx_assert(&(sc)->sc_mtx, t)
+#define	RUN_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
+#define	RUN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
+#define	RUN_LOCK_ASSERT(sc, t)	mtx_assert(&(sc)->sc_mtx, t)
+
+#define	RUN_CMDQ_LOCK(sc)		mtx_lock(&(sc)->sc_cmdq_mtx)
+#define	RUN_CMDQ_UNLOCK(sc)		mtx_unlock(&(sc)->sc_cmdq_mtx)
+#define	RUN_CMDQ_LOCK_ASSERT(sc, t)	mtx_assert(&(sc)->sc_cmdq_mtx, t)
 
 #endif	/* _IF_RUNVAR_H_ */


More information about the p4-projects mailing list