PERFORCE change 177777 for review

Hans Petter Selasky hselasky at FreeBSD.org
Wed May 5 19:56:36 UTC 2010


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

Change 177777 by hselasky at hselasky_laptop001 on 2010/05/05 19:55:35

	
	USB WLAN:
		- integrate latest version of RUN driver from:
	
		http://gitorious.org/run/run/trees/master/dev/usb/wlan

Affected files ...

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

Differences ...

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

@@ -39,7 +39,6 @@
 #include <sys/module.h>
 #include <sys/bus.h>
 #include <sys/endian.h>
-#include <sys/systm.h>
 #include <sys/linker.h>
 #include <sys/firmware.h>
 #include <sys/kdb.h>
@@ -66,20 +65,22 @@
 #include <net80211/ieee80211_regdomain.h>
 #include <net80211/ieee80211_radiotap.h>
 #include <net80211/ieee80211_amrr.h>
+#include <net80211/ieee80211_ratectl.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include "usbdevs.h"
 
 #define USB_DEBUG_VAR run_debug
+#define	USB_DEBUG	/*XXX remove this before commit */
 #include <dev/usb/usb_debug.h>
 
-#include "if_runreg.h"		/* shared with ral(4) */
+#include "if_runreg.h"
 #include "if_runvar.h"
 
 #define nitems(_a)      (sizeof((_a)) / sizeof((_a)[0]))
 
-#if	USB_DEBUG
+#ifdef	USB_DEBUG
 #define RUN_DEBUG
 #endif
 
@@ -93,6 +94,12 @@
 #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) },
@@ -290,7 +297,6 @@
 };
 
 MODULE_DEPEND(run, wlan, 1, 1, 1);
-MODULE_DEPEND(run, wlan_amrr, 1, 1, 1);
 MODULE_DEPEND(run, usb, 1, 1, 1);
 MODULE_DEPEND(run, firmware, 1, 1, 1);
 
@@ -313,6 +319,7 @@
 		    const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t
 		    mac[IEEE80211_ADDR_LEN]);
 static void	run_vap_delete(struct ieee80211vap *);
+static void	run_cmdq_cb(void *, int);
 static void	run_setup_tx_list(struct run_softc *,
 		    struct run_endpoint_queue *);
 static void	run_unsetup_tx_list(struct run_softc *,
@@ -343,23 +350,24 @@
 static int	run_media_change(struct ifnet *);
 static int	run_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static int	run_wme_update(struct ieee80211com *);
-static void	run_wme_update_cb(void *, int);
+static void	run_wme_update_cb(void *);
 static void	run_key_update_begin(struct ieee80211vap *);
 static void	run_key_update_end(struct ieee80211vap *);
-static int	run_key_set(struct ieee80211vap *, const struct ieee80211_key *,
+static void	run_key_set_cb(void *);
+static int	run_key_set(struct ieee80211vap *, struct ieee80211_key *,
 			    const uint8_t mac[IEEE80211_ADDR_LEN]);
-static int	run_key_delete(struct ieee80211vap *,
-		    const struct ieee80211_key *);
-static void	run_amrr_start(struct run_softc *, struct ieee80211_node *);
-static void	run_amrr_to(void *);
-static void	run_amrr_cb(void *, int);
+static void	run_key_delete_cb(void *);
+static int	run_key_delete(struct ieee80211vap *, struct ieee80211_key *);
+static void	run_ratectl_to(void *);
+static void	run_ratectl_cb(void *, int);
+static void	run_drain_fifo(void *);
 static void	run_iter_func(void *, struct ieee80211_node *);
+static void	run_newassoc_cb(void *);
 static void	run_newassoc(struct ieee80211_node *, int);
 static void	run_rx_frame(struct run_softc *, struct mbuf *, uint32_t);
 static void	run_tx_free(struct run_endpoint_queue *pq,
 		    struct run_tx_data *, int);
-static void	run_set_tx_desc(struct run_softc *, struct run_tx_data *,
-		    uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);
+static void	run_set_tx_desc(struct run_softc *, struct run_tx_data *);
 static int	run_tx(struct run_softc *, struct mbuf *,
 		    struct ieee80211_node *);
 static int	run_tx_mgt(struct run_softc *, struct mbuf *,
@@ -383,11 +391,10 @@
 static void	run_set_channel(struct ieee80211com *);
 static void	run_scan_start(struct ieee80211com *);
 static void	run_scan_end(struct ieee80211com *);
-static uint8_t	run_rate2mcs(uint8_t);
 static void	run_update_beacon(struct ieee80211vap *, int);
-static void	run_update_beacon_locked(struct ieee80211vap *, int);
+static void	run_update_beacon_cb(void *);
 static void	run_updateprot(struct ieee80211com *);
-static void	run_usb_timeout_cb(void *, int);
+static void	run_usb_timeout_cb(void *);
 static void	run_reset_livelock(struct run_softc *);
 static void	run_enable_tsf_sync(struct run_softc *);
 static void	run_enable_mrr(struct run_softc *);
@@ -397,6 +404,7 @@
 static void	run_set_bssid(struct run_softc *, const uint8_t *);
 static void	run_set_macaddr(struct run_softc *, const uint8_t *);
 static void	run_updateslot(struct ifnet *);
+static void	run_update_mcast(struct ifnet *);
 static int8_t	run_rssi2dbm(struct run_softc *, uint8_t, uint8_t);
 static void	run_update_promisc_locked(struct ifnet *);
 static void	run_update_promisc(struct ifnet *);
@@ -412,7 +420,7 @@
 static void	run_delay(struct run_softc *, unsigned int);
 
 static const struct {
-	uint32_t	reg;
+	uint16_t	reg;
 	uint32_t	val;
 } rt2870_def_mac[] = {
 	RT2870_DEF_MAC
@@ -552,6 +560,7 @@
 	    MTX_NETWORK_LOCK, MTX_DEF);
 
 	iface_index = RT2860_IFACE_INDEX;
+
 	error = usbd_transfer_setup(uaa->device, &iface_index,
 	    sc->sc_xfer, run_config, RUN_N_XFER, sc, &sc->sc_mtx);
 	if (error) {
@@ -617,15 +626,15 @@
 	ic->ic_ifp = ifp;
 	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
 	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
-#if 0
-	ic->ic_state = IEEE80211_S_INIT;
-#endif
+
 	/* set device capabilities */
 	ic->ic_caps =
 	    IEEE80211_C_STA |		/* station mode supported */
 	    IEEE80211_C_MONITOR |	/* monitor mode supported */
 	    IEEE80211_C_IBSS |
 	    IEEE80211_C_HOSTAP |
+	    IEEE80211_C_WDS |		/* 4-address traffic works */
+	    IEEE80211_C_MBSS |
 	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
 	    IEEE80211_C_SHSLOT |	/* short slot time supported */
 	    IEEE80211_C_WME |		/* WME */
@@ -672,6 +681,7 @@
 	ic->ic_node_alloc = run_node_alloc;
 	ic->ic_newassoc = run_newassoc;
 	//ic->ic_updateslot = run_updateslot;
+	ic->ic_update_mcast = run_update_mcast;
 	ic->ic_wme.wme_update = run_wme_update;
 	ic->ic_raw_xmit = run_raw_xmit;
 	ic->ic_update_promisc = run_update_promisc;
@@ -685,6 +695,10 @@
 	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
 		RUN_RX_RADIOTAP_PRESENT);
 
+	TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc);
+	TASK_INIT(&sc->ratectl_task, 0, run_ratectl_cb, sc);
+	callout_init((struct callout *)&sc->ratectl_ch, 1);
+
 	if (bootverbose)
 		ieee80211_announce(ic);
 
@@ -703,6 +717,8 @@
 	struct ieee80211com *ic;
 	int i;
 
+	DPRINTF("called\n");
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER);
 
@@ -710,16 +726,23 @@
 	/* free TX list, if any */
 	for (i = 0; i != RUN_EP_QUEUES; i++)
 		run_unsetup_tx_list(sc, &sc->sc_epq[i]);
+
 	RUN_UNLOCK(sc);
 
 	if (ifp) {
 		ic = ifp->if_l2com;
+		/* drain tasks */
+		usb_callout_drain(&sc->ratectl_ch);
+		ieee80211_draintask(ic, &sc->cmdq_task);
+		ieee80211_draintask(ic, &sc->ratectl_task);
 		ieee80211_ifdetach(ic);
 		if_free(ifp);
 	}
 
 	mtx_destroy(&sc->sc_mtx);
 
+	DPRINTF("done\n");
+
 	return (0);
 }
 
@@ -729,43 +752,92 @@
     const uint8_t bssid[IEEE80211_ADDR_LEN],
     const uint8_t mac[IEEE80211_ADDR_LEN])
 {
-	struct run_softc *sc = ic->ic_ifp->if_softc;
+	struct ifnet *ifp = ic->ic_ifp;
+	struct run_softc *sc = ifp->if_softc;
 	struct run_vap *rvp;
 	struct ieee80211vap *vap;
+	int i;
 
-	if (!TAILQ_EMPTY(&ic->ic_vaps))         /* only one at a time */
+	if(sc->rvp_cnt >= RUN_VAP_MAX){
+		if_printf(ifp, "number of VAPs maxed out\n");
+		return NULL;
+	}
+
+	switch (opmode) {
+	case IEEE80211_M_STA:
+		/* enable s/w bmiss handling for sta mode */
+		flags |= IEEE80211_CLONE_NOBEACONS; 
+		/* fall though */
+	case IEEE80211_M_IBSS:
+	case IEEE80211_M_MONITOR:
+	case IEEE80211_M_HOSTAP:
+	case IEEE80211_M_MBSS:
+		/* other than WDS vaps, only one at a time */
+		if (!TAILQ_EMPTY(&ic->ic_vaps))
+			return NULL;
+		break;
+	case IEEE80211_M_WDS:
+		TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next){
+			if(vap->iv_opmode != IEEE80211_M_HOSTAP)
+				continue;
+			/* WDS vap's always share the local mac address. */
+			flags &= ~IEEE80211_CLONE_BSSID;
+			break;
+		}
+		if(vap == NULL){
+			if_printf(ifp, "wds only supported in ap mode\n");
+			return NULL;
+		}
+		break;
+	default:
+		if_printf(ifp, "unknown opmode %d\n", opmode);
 		return NULL;
-	sc->sc_rvp = rvp = (struct run_vap *) malloc(sizeof(struct run_vap),
+	}
+
+	rvp = (struct run_vap *) malloc(sizeof(struct run_vap),
 	    M_80211_VAP, M_NOWAIT | M_ZERO);
 	if (rvp == NULL)
 		return NULL;
 	vap = &rvp->vap;
-	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
 
 	vap->iv_key_update_begin = run_key_update_begin;
 	vap->iv_key_update_end = run_key_update_end;
-	vap->iv_key_delete = run_key_delete;
-	vap->iv_key_set = run_key_set;
 	vap->iv_update_beacon = run_update_beacon;
+	vap->iv_max_aid = RT2870_WCID_MAX;
+	/*
+	 * To delete the right key from h/w, we need wcid.
+	 * Luckily, there is unused space in ieee80211_key{}, wk_pad,
+	 * and matching wcid will be written into there. So, cast
+	 * some spells to remove 'const' from ieee80211_key{}
+	 */
+	vap->iv_key_delete = (void *)run_key_delete;
+	vap->iv_key_set = (void *)run_key_set;
 
 	/* override state transition machine */
 	rvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = run_newstate;
 
-	TASK_INIT(&rvp->amrr_task, 0, run_amrr_cb, rvp);
-	TASK_INIT(&sc->wme_task, 0, run_wme_update_cb, ic);
-	TASK_INIT(&sc->usb_timeout_task, 0, run_usb_timeout_cb, sc);
-	callout_init((struct callout *)&rvp->amrr_ch, 1);
-	ieee80211_amrr_init(&rvp->amrr, vap,
-	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
-	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
-	    1000 /* 1 sec */);
+	ieee80211_ratectl_init(vap);
+	ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
 
 	/* complete setup */
 	ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status);
-	ic->ic_opmode = opmode;
+
+	/* make sure id is always unique */
+	for(i = 0; i < RUN_VAP_MAX; i++){
+		if((sc->rvp_bmap & 1 << i) == 0){
+			sc->rvp_bmap |= 1 << i;
+			rvp->rvp_id = i;
+			break;
+		}
+	}
+	if(sc->rvp_cnt++ == 0)
+		ic->ic_opmode = opmode;
+
+	DPRINTF("rvp_id=%d bmap=%x rvp_cnt=%d\n",
+	    rvp->rvp_id, sc->rvp_bmap, sc->rvp_cnt);
+
 	return vap;
 }
 
@@ -776,6 +848,7 @@
 	struct ifnet *ifp;
 	struct ieee80211com *ic;
 	struct run_softc *sc;
+	uint8_t rvp_id;
 
 	if(vap == NULL)
 		return;
@@ -786,19 +859,59 @@
 	sc = ifp->if_softc;
 
 	RUN_LOCK(sc);
-	sc->sc_rvp->amrr_run = RUN_AMRR_OFF;
+
+	rvp_id = rvp->rvp_id;
+	sc->ratectl_run &= ~(1 << rvp_id);
+	sc->rvp_bmap &= ~(1 << rvp_id);
+	run_set_region_4(sc, RT2860_SKEY(rvp_id, 0), 0, 128);
+	run_set_region_4(sc, RT2860_BCN_BASE(rvp_id), 0, 512);
+	--sc->rvp_cnt;
+
+	DPRINTF("vap=%p rvp_id=%d bmap=%x rvp_cnt=%d\n",
+	    vap, rvp_id, sc->rvp_bmap, sc->rvp_cnt);
+
 	RUN_UNLOCK(sc);
 
-	/* drain them all */
-	usb_callout_drain(&sc->sc_rvp->amrr_ch);
-	ieee80211_draintask(ic, &sc->sc_rvp->amrr_task);
-	ieee80211_draintask(ic, &sc->wme_task);
-	ieee80211_draintask(ic, &sc->usb_timeout_task);
-
-	ieee80211_amrr_cleanup(&rvp->amrr);
+	ieee80211_ratectl_deinit(vap);
 	ieee80211_vap_detach(vap);
 	free(rvp, M_80211_VAP);
-	sc->sc_rvp = NULL;
+}
+
+/*
+ * There are numbers of functions need to be called in context thread.
+ * Rather than creating taskqueue event for each of those functions,
+ * here is all-for-one taskqueue callback function. This function
+ * gurantees deferred functions are executed in the same order they
+ * were enqueued.
+ * '& RUN_CMDQ_MASQ' is to loop cmdq[].
+ */
+static void
+run_cmdq_cb(void *arg, int pending)
+{
+	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--){
+		DPRINTFN(6, "cmdq_exec=%d pending=%d\n", i, pending);
+		if(sc->cmdq_run == RUN_CMDQ_GO){
+			/*
+			 * If arg0 is NULL, callback func needs more
+			 * than one arg. So, pass ptr to cmdq struct.
+			 */
+			if(sc->cmdq[i].arg0)
+				sc->cmdq[i].func(sc->cmdq[i].arg0);
+			else
+				sc->cmdq[i].func(&sc->cmdq[i]);
+		}
+		sc->cmdq[i].arg0 = NULL;
+		sc->cmdq[i].func = NULL;
+		sc->cmdq_exec++;
+		sc->cmdq_exec &= RUN_CMDQ_MASQ;
+	}
+	RUN_UNLOCK(sc);
 }
 
 static void
@@ -1331,14 +1444,14 @@
 	sc->sc_srom_read = run_eeprom_read_2;
 	if (sc->mac_ver >= 0x3070) {
 		run_read(sc, RT3070_EFUSE_CTRL, &tmp);
-		DPRINTF("EFUSE_CTRL=0x%08x\n", tmp);
+		DPRINTFN(2, "EFUSE_CTRL=0x%08x\n", tmp);
 		if (tmp & RT3070_SEL_EFUSE)
 			sc->sc_srom_read = run_efuse_read_2;
 	}
 
 	/* read ROM version */
 	run_srom_read(sc, RT2860_EEPROM_VERSION, &val);
-	DPRINTF("EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8);
+	DPRINTFN(2, "EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8);
 
 	/* read MAC address */
 	run_srom_read(sc, RT2860_EEPROM_MAC01, &val);
@@ -1356,7 +1469,7 @@
 		run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
 		sc->bbp[i].val = val & 0xff;
 		sc->bbp[i].reg = val >> 8;
-		DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val);
+		DPRINTFN(2, "BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val);
 	}
 	if (sc->mac_ver >= 0x3071) {
 		/* read vendor RF settings */
@@ -1364,7 +1477,7 @@
 			run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val);
 			sc->rf[i].val = val & 0xff;
 			sc->rf[i].reg = val >> 8;
-			DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
+			DPRINTFN(2, "RF%d=0x%02x\n", sc->rf[i].reg,
 			    sc->rf[i].val);
 		}
 	}
@@ -1372,7 +1485,7 @@
 	/* read RF frequency offset from EEPROM */
 	run_srom_read(sc, RT2860_EEPROM_FREQ_LEDS, &val);
 	sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0;
-	DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff);
+	DPRINTFN(2, "EEPROM freq offset %d\n", sc->freq & 0xff);
 
 	if (val >> 8 != 0xff) {
 		/* read LEDs operating mode */
@@ -1387,7 +1500,7 @@
 		sc->led[1] = 0x2221;
 		sc->led[2] = 0x5627;	/* differs from RT2860 */
 	}
-	DPRINTF("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
+	DPRINTFN(2, "EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
 	    sc->leds, sc->led[0], sc->led[1], sc->led[2]);
 
 	/* read RF information */
@@ -1418,8 +1531,9 @@
 	DPRINTF("EEPROM RF rev=0x%02x chains=%dT%dR\n",
 	    sc->rf_rev, sc->ntxchains, sc->nrxchains);
 
+	/* check if RF supports automatic Tx access gain control */
 	run_srom_read(sc, RT2860_EEPROM_CONFIG, &val);
-	DPRINTF("EEPROM CFG 0x%04x\n", val);
+	DPRINTFN(2, "EEPROM CFG 0x%04x\n", val);
 	/* check if driver should patch the DAC issue */
 	if ((val >> 8) != 0xff)
 		sc->patch_dac = (val >> 15) & 1;
@@ -1448,7 +1562,7 @@
 			sc->txpow1[i] = 5;
 		if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
 			sc->txpow2[i] = 5;
-		DPRINTF("chan %d: power1=%d, power2=%d\n",
+		DPRINTFN(2, "chan %d: power1=%d, power2=%d\n",
 		    rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
 	}
 	/* read power settings for 5GHz channels */
@@ -1467,7 +1581,7 @@
 			sc->txpow1[14 + i] = 5;
 		if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
 			sc->txpow2[14 + i] = 5;
-		DPRINTF("chan %d: power1=%d, power2=%d\n",
+		DPRINTFN(2, "chan %d: power1=%d, power2=%d\n",
 		    rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
 		    sc->txpow2[14 + i]);
 	}
@@ -1486,22 +1600,22 @@
 		if (!(val & 0x40))	/* negative number */
 			delta_5ghz = -delta_5ghz;
 	}
-	DPRINTF("power compensation=%d (2GHz), %d (5GHz)\n",
+	DPRINTFN(2, "power compensation=%d (2GHz), %d (5GHz)\n",
 	    delta_2ghz, delta_5ghz);
 
 	for (ridx = 0; ridx < 5; ridx++) {
 		uint32_t reg;
 
-		run_srom_read(sc, RT2860_EEPROM_RPWR + ridx, &val);
-		reg = (uint32_t)val << 16;
-		run_srom_read(sc, RT2860_EEPROM_RPWR + ridx + 1, &val);
-		reg |= val;
+		run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2, &val);
+		reg = val;
+		run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1, &val);
+		reg |= (uint32_t)val << 16;
 
 		sc->txpow20mhz[ridx] = reg;
 		sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz);
 		sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz);
 
-		DPRINTF("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, "
+		DPRINTFN(2, "ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, "
 		    "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx],
 		    sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]);
 	}
@@ -1518,7 +1632,7 @@
 		 */
 		if ((val & 0xff) != 0xff)
 			sc->txmixgain_2ghz = val & 0x7;
-		DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz);
+		DPRINTFN(2, "tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz);
 	} else
 		sc->rssi_2ghz[2] = val & 0xff;	/* Ant C */
 	sc->lna[2] = val >> 8;		/* channel group 2 */
@@ -1534,7 +1648,7 @@
 		 */
 		if ((val & 0xff) != 0xff)
 			sc->txmixgain_5ghz = val & 0x7;
-		DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz);
+		DPRINTFN(2, "tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz);
 	} else
 		sc->rssi_5ghz[2] = val & 0xff;	/* Ant C */
 	sc->lna[3] = val >> 8;		/* channel group 3 */
@@ -1578,19 +1692,23 @@
 static int
 run_media_change(struct ifnet *ifp)
 {
+	struct ieee80211vap *vap = ifp->if_softc;
+	struct ieee80211com *ic = vap->iv_ic;
 	const struct ieee80211_txparam *tp;
-	struct run_softc *sc = ifp->if_softc;
-	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
-	struct ieee80211vap *vap = &sc->sc_rvp->vap;
+	struct run_softc *sc = ic->ic_ifp->if_softc;
+	struct run_node	*rn = (void *)vap->iv_bss;
 	uint8_t rate, ridx;
 	int error;
 
+	DPRINTF("called\n");
+
 	RUN_LOCK(sc);
 
 	error = ieee80211_media_change(ifp);
-	if (error != ENETRESET)
+	if (error != ENETRESET){
 		RUN_UNLOCK(sc);
 		return error;
+	}
 
 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
 	if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
@@ -1599,13 +1717,16 @@
 		for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
 			if (rt2860_rates[ridx].rate == rate)
 				break;
-		sc->fixed_ridx = ridx;
+		rn->fix_ridx = ridx;
+		DPRINTF("rate=%d, fix_ridx=%d\n", rate, rn->fix_ridx);
 	}
 
+#if 0
 	if ((ifp->if_flags & IFF_UP) &&
 	    (ifp->if_drv_flags &  IFF_DRV_RUNNING)){
 		run_init_locked(sc);
 	}
+#endif
 
 	RUN_UNLOCK(sc);
 
@@ -1621,8 +1742,11 @@
 	struct run_vap *rvp = RUN_VAP(vap);
 	enum ieee80211_state ostate;
 	struct ieee80211_node *ni;
+	uint32_t sta[3];
 	uint32_t tmp;
-	uint8_t wcid;
+	uint8_t ratectl;
+	uint8_t restart_ratectl = 0;
+	uint8_t bid = 1 << rvp->rvp_id;
 
 	ostate = vap->iv_state;
 	DPRINTF("%s -> %s\n",
@@ -1632,8 +1756,9 @@
 	IEEE80211_UNLOCK(ic);
 	RUN_LOCK(sc);
 
-	sc->sc_rvp->amrr_run = RUN_AMRR_OFF;
-	usb_callout_stop(&rvp->amrr_ch);
+	ratectl = sc->ratectl_run; /* remember current state */
+	sc->ratectl_run = RUN_RATECTL_OFF;
+	usb_callout_stop(&sc->ratectl_ch);
 
 	if (ostate == IEEE80211_S_RUN) {
 		/* turn link LED off */
@@ -1642,8 +1767,16 @@
 
 	switch (nstate) {
 	case IEEE80211_S_INIT:
-		if (ostate == IEEE80211_S_RUN) {
-			/* abort TSF synchronization */
+		restart_ratectl = 1;
+
+		if (ostate != IEEE80211_S_RUN)
+			break;
+
+		ratectl &= ~bid;
+		sc->runbmap &= ~bid;
+
+		/* abort TSF synchronization if there is no vap running */
+		if(--sc->running == 0){
 			run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
 			run_write(sc, RT2860_BCN_TIME_CFG,
 			    tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
@@ -1651,9 +1784,43 @@
 		}
 		break;
 
+
 	case IEEE80211_S_RUN:
 		ni = vap->iv_bss;
+		if(!(sc->runbmap & bid)){
+			if(sc->running++)
+				restart_ratectl = 1;
+			sc->runbmap |= bid;
+		}
+
+		switch(vap->iv_opmode){
+		case IEEE80211_M_HOSTAP:
+		case IEEE80211_M_MBSS:
+			sc->ap_running |= bid;
+			ic->ic_opmode = vap->iv_opmode;
+			run_update_beacon_cb(vap);
+			break;
+		case IEEE80211_M_IBSS:
+			sc->adhoc_running |= bid;
+			if(!sc->ap_running)
+				ic->ic_opmode = vap->iv_opmode;
+			run_update_beacon_cb(vap);
+			break;
+		case IEEE80211_M_STA:
+			sc->sta_running |= bid;
+			if(!sc->ap_running && !sc->adhoc_running)
+				ic->ic_opmode = vap->iv_opmode;
+
+			/* read statistic counters (clear on read) */
+			run_read_region_1(sc, RT2860_TX_STA_CNT0,
+			    (uint8_t *)sta, sizeof sta);
 
+			break;
+		default:
+			ic->ic_opmode = vap->iv_opmode;
+			break;
+		}
+
 		if (vap->iv_opmode != IEEE80211_M_MONITOR) {
 			run_updateslot(ic->ic_ifp);
 			run_enable_mrr(sc);
@@ -1661,31 +1828,17 @@
 			run_set_basicrates(sc);
 			IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
 			run_set_bssid(sc, ni->ni_bssid);
-		}
+			run_enable_tsf_sync(sc);
 
-		if (vap->iv_opmode == IEEE80211_M_STA) {
-			/* add BSS entry to the WCID table */
-			wcid = RUN_AID2WCID(ni->ni_associd);
-			run_write_region_1(sc, RT2860_WCID_ENTRY(wcid),
-			    ni->ni_macaddr, IEEE80211_ADDR_LEN);
+			/* enable automatic rate adaptation */
+			tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
+			if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
+				ratectl |= bid;
 		}
 
-		if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
-		    vap->iv_opmode == IEEE80211_M_IBSS)
-			run_update_beacon_locked(vap, 0);
-
-		if (vap->iv_opmode != IEEE80211_M_MONITOR) {
-			run_enable_tsf_sync(sc);
-		} /* else tsf */
-
-		/* enable automatic rate adaptation */
-		tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
-		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
-			run_amrr_start(sc, ni);
-
 		/* turn link LED on */
 		run_set_leds(sc, RT2860_LED_RADIO |
-		    (IEEE80211_IS_CHAN_2GHZ(vap->iv_bss->ni_chan) ?
+		    (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ?
 		     RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ));
 
 		break;
@@ -1694,34 +1847,28 @@
 		break;
 	}
 
+	/* restart amrr for running VAPs */
+	if((sc->ratectl_run = ratectl) && restart_ratectl)
+		usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+
 	RUN_UNLOCK(sc);
 	IEEE80211_LOCK(ic);
 
 	return(rvp->newstate(vap, nstate, arg));
 }
 
-/* another taskqueue, so usbd_do_request() can go sleep */
-static int
-run_wme_update(struct ieee80211com *ic)
-{
-	struct run_softc *sc = ic->ic_ifp->if_softc;
-
-	ieee80211_runtask(ic, &sc->wme_task);
-
-	/* return whatever, upper layer desn't care anyway */
-	return 0;
-}
-
 /* ARGSUSED */
 static void
-run_wme_update_cb(void *arg, int pending)
+run_wme_update_cb(void *arg)
 {
 	struct ieee80211com *ic = arg;
 	struct run_softc *sc = ic->ic_ifp->if_softc;
 	struct ieee80211_wme_state *wmesp = &ic->ic_wme;
 	int aci, error = 0;
 
-	RUN_LOCK(sc);
+	DPRINTF("called\n");
+
+	RUN_LOCK_ASSERT(sc, MA_OWNED);
 
 	/* update MAC TX configuration registers */
 	for (aci = 0; aci < WME_NUM_AC; aci++) {
@@ -1764,19 +1911,41 @@
 	if(error)
 		DPRINTF("WME update failed\n");
 
+	return;
+}
+
+static int
+run_wme_update(struct ieee80211com *ic)
+{
+	struct run_softc *sc = ic->ic_ifp->if_softc;
+
+	DPRINTF("called\n");
+
+	/* 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);
+		sc->cmdq[i].func = run_wme_update_cb;
+		sc->cmdq[i].arg0 = ic;
+		ieee80211_runtask(ic, &sc->cmdq_task);
+		return (0);
+	}
+
+	RUN_LOCK(sc);
+	run_wme_update_cb(ic);
 	RUN_UNLOCK(sc);
-	return;
+
+	/* return whatever, upper layer desn't care anyway */
+	return (0);
 }
 
 static void
 run_key_update_begin(struct ieee80211vap *vap)
 {
 	/*
-	 * Because run_key_delete() needs special attention
-	 * on lock related operation, lock handling is being done
-	 * differently in run_key_set and _delete.
-	 *
-	 * So, we don't use key_update_begin and _end.
+	 * To avoid out-of-order events, both run_key_set() and
+	 * _delete() are deferred and handled by run_cmdq_cb().
+	 * So, there is nothing we need to do here.
 	 */
 }
 
@@ -1786,37 +1955,31 @@
 	/* null */
 }
 
-/*
- * return 0 on error
- */
-static int
-run_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
-		const uint8_t mac[IEEE80211_ADDR_LEN])
+static void
+run_key_set_cb(void *arg)
 {
+	struct run_cmdq *cmdq = arg;
+	struct ieee80211vap *vap = cmdq->arg1;
+	struct ieee80211_key *k = cmdq->k;
 	struct ieee80211com *ic = vap->iv_ic;
-	struct ifnet *ifp = ic->ic_ifp;
-	struct run_softc *sc = ifp->if_softc;
+	struct run_softc *sc = ic->ic_ifp->if_softc;
 	struct ieee80211_node *ni;
 	uint32_t attr;
 	uint16_t base, associd;
 	uint8_t mode, wcid, txmic, rxmic, iv[8];
-	int error = 0;
 
-	RUN_LOCK(sc);
+	RUN_LOCK_ASSERT(sc, MA_OWNED);
 
 	if(vap->iv_opmode == IEEE80211_M_HOSTAP){
-		ni = ieee80211_find_vap_node(&ic->ic_sta, vap, mac);
-		associd = (ni != NULL) ? ni->ni_associd : 0;
-		if(ni != NULL)
-			ieee80211_free_node(ni);
+		ni = ieee80211_find_vap_node(&ic->ic_sta, vap, cmdq->mac);
 		txmic = 24;
 		rxmic = 16;
 	} else {
 		ni = vap->iv_bss;
-		associd = (ni != NULL) ? ni->ni_associd : 0;
 		txmic = 16;
 		rxmic = 24;
 	}
+	associd = (ni != NULL) ? ni->ni_associd : 0;
 
 	/* map net80211 cipher to RT2860 security mode */
 	switch (k->wk_cipher->ic_cipher) {
@@ -1834,16 +1997,18 @@
 		break;
 	default:
 		DPRINTF("undefined case\n");
-		goto fail;
+		return;
 	}
 
-	DPRINTFN(1, "associd=%x, keyix=%d, mode=%x, type=%s\n",
+	DPRINTFN(1, "associd=%x, keyix=%d, mode=%x, type=%s, tx=%s, rx=%s\n",
 	    associd, k->wk_keyix, mode,
-	    (k->wk_flags & IEEE80211_KEY_GROUP) ? "group" : "pairwise");
+	    (k->wk_flags & IEEE80211_KEY_GROUP) ? "group" : "pairwise",
+	    (k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off",
+	    (k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off");
 
 	if (k->wk_flags & IEEE80211_KEY_GROUP) {
 		wcid = 0;	/* NB: update WCID0 for group keys */
-		base = RT2860_SKEY(0, k->wk_keyix);
+		base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix);
 	} else {
 		wcid = RUN_AID2WCID(associd);
 		base = RT2860_PKEY(wcid);
@@ -1851,15 +2016,15 @@
 
 	if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) {
 		if(run_write_region_1(sc, base, k->wk_key, 16))
-			goto fail;
+			return;
 		if(run_write_region_1(sc, base + 16, &k->wk_key[txmic], 8))	/* wk_txmic */
-			goto fail;
+			return;
 		if(run_write_region_1(sc, base + 24, &k->wk_key[rxmic], 8))	/* wk_rxmic */
-			goto fail;
+			return;
 	} else {
 		/* roundup len to 16-bit: XXX fix write_region_1() instead */
 		if(run_write_region_1(sc, base, k->wk_key, (k->wk_keylen + 1) & ~1))
-			goto fail;
+			return;
 	}
 
 	if (!(k->wk_flags & IEEE80211_KEY_GROUP) ||
@@ -1867,7 +2032,7 @@
 		/* set initial packet number in IV+EIV */
 		if (k->wk_cipher == IEEE80211_CIPHER_WEP){
 			memset(iv, 0, sizeof iv);
-			iv[3] = sc->sc_rvp->vap.iv_def_txkey << 6;
+			iv[3] = vap->iv_def_txkey << 6;
 		} else {
 			if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) {
 				iv[0] = k->wk_keytsc >> 8;
@@ -1885,127 +2050,150 @@
 			iv[7] = k->wk_keytsc >> 40;
 		}
 		if(run_write_region_1(sc, RT2860_IVEIV(wcid), iv, 8))
-			goto fail;
+			return;
 	}
 
 	if (k->wk_flags & IEEE80211_KEY_GROUP) {
 		/* install group key */
 		if(run_read(sc, RT2860_SKEY_MODE_0_7, &attr))
-			goto fail;
+			return;
 		attr &= ~(0xf << (k->wk_keyix * 4));
 		attr |= mode << (k->wk_keyix * 4);
 		if(run_write(sc, RT2860_SKEY_MODE_0_7, attr))
-			goto fail;
+			return;
 	} else {
 		/* install pairwise key */
 		if(run_read(sc, RT2860_WCID_ATTR(wcid), &attr))
-			goto fail;
+			return;
 		attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN;
 		if(run_write(sc, RT2860_WCID_ATTR(wcid), attr))
-			goto fail;
+			return;
 	}
 
 	/* TODO create a pass-thru key entry? */
 
-fail:
-	RUN_UNLOCK(sc);
-	return (error? 0 : 1);
+	/* need wcid to delete the right key later */
+	k->wk_pad = wcid;
 }
 
 /*
+ * Don't have to be deferred, but in order to keep order of
+ * execution, i.e. with run_key_delete(), defer this and let
+ * run_cmdq_cb() maintain the order.
+ *
  * return 0 on error
  */
 static int
-run_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
+run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
+		const uint8_t mac[IEEE80211_ADDR_LEN])
 {
 	struct ieee80211com *ic = vap->iv_ic;
 	struct run_softc *sc = ic->ic_ifp->if_softc;
-	struct ieee80211_node *ni = vap->iv_bss;
-	struct ieee80211_node_table *nt = &ic->ic_sta;
+	uint32_t i;
+
+	i = RUN_CMDQ_GET(&sc->cmdq_store);
+	DPRINTF("cmdq_store=%d\n", i);
+	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);
+
+	return(1);
+}
+
+/*
+ * If wlan is destroyed without being brought down i.e. without
+ * wlan down or wpa_cli terminate, this function is called after
+ * vap is gone. Don't refer it.
+ */
+static void
+run_key_delete_cb(void *arg)
+{
+	struct run_cmdq *cmdq = arg;
+	struct run_softc *sc = cmdq->arg1;
+	struct ieee80211_key *k = &cmdq->key;
 	uint32_t attr;
 	uint8_t wcid;
-	int error = 0;
-	uint8_t nislocked, cislocked;
 
-	if((nislocked = IEEE80211_NODE_IS_LOCKED(nt)))
-		IEEE80211_NODE_UNLOCK(nt);
-	if((cislocked = mtx_owned(&ic->ic_comlock.mtx)))
-		IEEE80211_UNLOCK(ic);
-	RUN_LOCK(sc);
+	RUN_LOCK_ASSERT(sc, MA_OWNED);
 
 	if (k->wk_flags & IEEE80211_KEY_GROUP) {
 		/* remove group key */
-		if(run_read(sc, RT2860_SKEY_MODE_0_7, &attr))
-			goto fail;
+		DPRINTF("removing group key\n");
+		run_read(sc, RT2860_SKEY_MODE_0_7, &attr);
 		attr &= ~(0xf << (k->wk_keyix * 4));

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list