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

Adrian Chadd adrian at FreeBSD.org
Fri Sep 18 07:55:34 UTC 2015


Author: adrian
Date: Fri Sep 18 07:55:33 2015
New Revision: 287954
URL: https://svnweb.freebsd.org/changeset/base/287954

Log:
  Add in a temporary (hah!) workaround for net80211 scanning versus NIC
  requirements.
  
  Don't start the opmode and join path until a pending survey is finished.
  This seems to reliably fix things.
  
  Ideally I'd just finish off the net80211 pluggable scan stuff and implement
  the methods here so if_rsu can just drive the scan machinery.
  However, that's a .. later thing.
  
  Whilst here, remove the getbuf debugging; it's okay to run out of transmit
  buffers under load; it however isn't okay to not be able to send commands.
  I'll fix that later.

Modified:
  head/sys/dev/usb/wlan/if_rsu.c
  head/sys/dev/usb/wlan/if_rsureg.h

Modified: head/sys/dev/usb/wlan/if_rsu.c
==============================================================================
--- head/sys/dev/usb/wlan/if_rsu.c	Fri Sep 18 07:26:34 2015	(r287953)
+++ head/sys/dev/usb/wlan/if_rsu.c	Fri Sep 18 07:55:33 2015	(r287954)
@@ -742,9 +742,7 @@ _rsu_getbuf(struct rsu_softc *sc)
 		STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
 	else
 		bf = NULL;
-	if (bf == NULL)
-		DPRINTF("out of xmit buffers\n");
-        return (bf);
+	return (bf);
 }
 
 static struct rsu_data *
@@ -755,8 +753,6 @@ rsu_getbuf(struct rsu_softc *sc)
 	RSU_ASSERT_LOCKED(sc);
 
 	bf = _rsu_getbuf(sc);
-	if (bf == NULL)
-		DPRINTF("stop queue\n");
 	return (bf);
 }
 
@@ -947,6 +943,8 @@ rsu_fw_cmd(struct rsu_softc *sc, uint8_t
 	int cmdsz;
 	int xferlen;
 
+	RSU_ASSERT_LOCKED(sc);
+
 	data = rsu_getbuf(sc);
 	if (data == NULL)
 		return (ENOMEM);
@@ -1124,6 +1122,9 @@ rsu_site_survey(struct rsu_softc *sc, st
 {
 	struct r92s_fw_cmd_sitesurvey cmd;
 	struct ieee80211com *ic = &sc->sc_ic;
+	int r;
+
+	RSU_ASSERT_LOCKED(sc);
 
 	memset(&cmd, 0, sizeof(cmd));
 	if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1)
@@ -1137,7 +1138,11 @@ rsu_site_survey(struct rsu_softc *sc, st
 
 	}
 	DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
-	return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
+	r = rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd));
+	if (r == 0) {
+		sc->sc_scanning = 1;
+	}
+	return (r);
 }
 
 static int
@@ -1152,6 +1157,27 @@ rsu_join_bss(struct rsu_softc *sc, struc
 	uint8_t *frm;
 	uint8_t opmode;
 	int error;
+	int cnt;
+	char *msg = "rsujoin";
+
+	RSU_ASSERT_LOCKED(sc);
+
+	/*
+	 * Until net80211 scanning doesn't automatically finish
+	 * before we tell it to, let's just wait until any pending
+	 * scan is done.
+	 *
+	 * XXX TODO: yes, this releases and re-acquires the lock.
+	 * We should re-verify the state whenever we re-attempt this!
+	 */
+	cnt = 0;
+	while (sc->sc_scanning && cnt < 10) {
+		device_printf(sc->sc_dev,
+		    "%s: still scanning! (attempt %d)\n",
+		    __func__, cnt);
+		msleep(msg, &sc->sc_mtx, 0, msg, hz / 2);
+		cnt++;
+	}
 
 	/* Let the FW decide the opmode based on the capinfo field. */
 	opmode = NDIS802_11AUTOUNKNOWN;
@@ -1309,12 +1335,18 @@ rsu_event_join_bss(struct rsu_softc *sc,
 	RSU_DPRINTF(sc, RSU_DEBUG_STATE | RSU_DEBUG_FWCMD,
 	    "%s: Rx join BSS event len=%d res=%d\n",
 	    __func__, len, res);
+
+	/*
+	 * XXX Don't do this; there's likely a better way to tell
+	 * the caller we failed.
+	 */
 	if (res <= 0) {
 		RSU_UNLOCK(sc);
 		ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
 		RSU_LOCK(sc);
 		return;
 	}
+
 	tmp = le32toh(rsp->associd);
 	if (tmp >= vap->iv_max_aid) {
 		DPRINTF("Assoc ID overflow\n");
@@ -1376,8 +1408,14 @@ rsu_rx_event(struct rsu_softc *sc, uint8
 		RSU_DPRINTF(sc, RSU_DEBUG_SCAN,
 		    "%s: site survey pass %d done, found %d BSS\n",
 		    __func__, sc->sc_scan_pass, le32toh(*(uint32_t *)buf));
+		sc->sc_scanning = 0;
 		if (vap->iv_state != IEEE80211_S_SCAN)
 			break;	/* Ignore if not scanning. */
+
+		/*
+		 * XXX TODO: This needs to be done without a transition to
+		 * the SCAN state again.  Grr.
+		 */
 		if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) {
 			/* Schedule a directed scan for hidden APs. */
 			/* XXX bad! */
@@ -2594,6 +2632,7 @@ rsu_init(struct rsu_softc *sc)
 
 	/* We're ready to go. */
 	sc->sc_running = 1;
+	sc->sc_scanning = 0;
 	return;
 fail:
 	/* Need to stop all failed transfers, if any */

Modified: head/sys/dev/usb/wlan/if_rsureg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_rsureg.h	Fri Sep 18 07:26:34 2015	(r287953)
+++ head/sys/dev/usb/wlan/if_rsureg.h	Fri Sep 18 07:55:33 2015	(r287954)
@@ -747,6 +747,7 @@ struct rsu_softc {
 
 	u_int				sc_running:1,
 					sc_calibrating:1,
+					sc_scanning:1,
 					sc_scan_pass:1;
 	u_int				cut;
 	struct rsu_host_cmd_ring	cmdq;


More information about the svn-src-head mailing list