svn commit: r309210 - head/sys/dev/usb/wlan
Andriy Voskoboinyk
avos at FreeBSD.org
Sun Nov 27 12:03:36 UTC 2016
Author: avos
Date: Sun Nov 27 12:03:34 2016
New Revision: 309210
URL: https://svnweb.freebsd.org/changeset/base/309210
Log:
rsu: various scanning fixes.
- Set IEEE80211_FEXT_SCAN_OFFLOAD flag; firmware can send null data
frames when associated.
- Check IEEE80211_SCAN_ACTIVE scan flag instead of IEEE80211_F_ASCAN
ic flag; the last is never set since r170530.
- Eliminate software scan (net80211) <-> site_survey (driver) race:
* override ic_scan_curchan and ic_scan_mindwell pointers so net80211
will not try to finish scanning automatically;
* inform net80211 about current status via ieee80211_cancel_scan()
and ieee80211_scan_done();
* remove corresponding workaround from rsu_join_bss().
Now the driver can associate to an AP with hidden SSID.
Tested with Asus USB-N10.
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 Sun Nov 27 09:20:58 2016 (r309209)
+++ head/sys/dev/usb/wlan/if_rsu.c Sun Nov 27 12:03:34 2016 (r309210)
@@ -173,6 +173,8 @@ static void rsu_scan_end(struct ieee8021
static void rsu_getradiocaps(struct ieee80211com *, int, int *,
struct ieee80211_channel[]);
static void rsu_set_channel(struct ieee80211com *);
+static void rsu_scan_curchan(struct ieee80211_scan_state *, unsigned long);
+static void rsu_scan_mindwell(struct ieee80211_scan_state *);
static void rsu_update_mcast(struct ieee80211com *);
static int rsu_alloc_rx_list(struct rsu_softc *);
static void rsu_free_rx_list(struct rsu_softc *);
@@ -203,7 +205,8 @@ static int rsu_newstate(struct ieee80211
static void rsu_set_key(struct rsu_softc *, const struct ieee80211_key *);
static void rsu_delete_key(struct rsu_softc *, const struct ieee80211_key *);
#endif
-static int rsu_site_survey(struct rsu_softc *, struct ieee80211vap *);
+static int rsu_site_survey(struct rsu_softc *,
+ struct ieee80211_scan_ssid *);
static int rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
static int rsu_disconnect(struct rsu_softc *);
static int rsu_hwrssi_to_rssi(struct rsu_softc *, int hw_rssi);
@@ -537,6 +540,7 @@ rsu_attach(device_t self)
ic->ic_txstream = sc->sc_ntxstream;
ic->ic_rxstream = sc->sc_nrxstream;
}
+ ic->ic_flags_ext |= IEEE80211_FEXT_SCAN_OFFLOAD;
rsu_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
ic->ic_channels);
@@ -547,6 +551,8 @@ rsu_attach(device_t self)
ic->ic_scan_end = rsu_scan_end;
ic->ic_getradiocaps = rsu_getradiocaps;
ic->ic_set_channel = rsu_set_channel;
+ ic->ic_scan_curchan = rsu_scan_curchan;
+ ic->ic_scan_mindwell = rsu_scan_mindwell;
ic->ic_vap_create = rsu_vap_create;
ic->ic_vap_delete = rsu_vap_delete;
ic->ic_update_mcast = rsu_update_mcast;
@@ -680,16 +686,21 @@ static void
rsu_scan_start(struct ieee80211com *ic)
{
struct rsu_softc *sc = ic->ic_softc;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int error;
/* Scanning is done by the firmware. */
RSU_LOCK(sc);
- /* XXX TODO: force awake if in in network-sleep? */
- error = rsu_site_survey(sc, TAILQ_FIRST(&ic->ic_vaps));
+ sc->sc_active_scan = !!(ss->ss_flags & IEEE80211_SCAN_ACTIVE);
+ /* XXX TODO: force awake if in network-sleep? */
+ error = rsu_site_survey(sc, ss->ss_nssid > 0 ? &ss->ss_ssid[0] : NULL);
RSU_UNLOCK(sc);
- if (error != 0)
+ if (error != 0) {
device_printf(sc->sc_dev,
"could not send site survey command\n");
+ ieee80211_cancel_scan(vap);
+ }
}
static void
@@ -722,6 +733,24 @@ rsu_set_channel(struct ieee80211com *ic
}
static void
+rsu_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
+{
+ /* Scan is done in rsu_scan_start(). */
+}
+
+/**
+ * Called by the net80211 framework to indicate
+ * the minimum dwell time has been met, terminate the scan.
+ * We don't actually terminate the scan as the firmware will notify
+ * us when it's finished and we have no way to interrupt it.
+ */
+static void
+rsu_scan_mindwell(struct ieee80211_scan_state *ss)
+{
+ /* NB: don't try to abort scan; wait for firmware to finish */
+}
+
+static void
rsu_update_mcast(struct ieee80211com *ic)
{
/* XXX do nothing? */
@@ -1323,31 +1352,36 @@ rsu_delete_key(struct rsu_softc *sc, con
#endif
static int
-rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap)
+rsu_site_survey(struct rsu_softc *sc, struct ieee80211_scan_ssid *ssid)
{
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)
+ /* TODO: passive channels? */
+ if (sc->sc_active_scan)
cmd.active = htole32(1);
cmd.limit = htole32(48);
- if (sc->sc_scan_pass == 1 && vap->iv_des_nssid > 0) {
- /* Do a directed scan for second pass. */
- cmd.ssidlen = htole32(vap->iv_des_ssid[0].len);
- memcpy(cmd.ssid, vap->iv_des_ssid[0].ssid,
- vap->iv_des_ssid[0].len);
-
+
+ if (ssid != NULL) {
+ sc->sc_extra_scan = 1;
+ cmd.ssidlen = htole32(ssid->len);
+ memcpy(cmd.ssid, ssid->ssid, ssid->len);
}
- DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
- r = rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd));
- if (r == 0) {
- sc->sc_scanning = 1;
+#ifdef USB_DEBUG
+ if (rsu_debug & (RSU_DEBUG_SCAN | RSU_DEBUG_FWCMD)) {
+ device_printf(sc->sc_dev,
+ "sending site survey command, active %d",
+ le32toh(cmd.active));
+ if (ssid != NULL) {
+ printf(", ssid: ");
+ ieee80211_print_essid(cmd.ssid, le32toh(cmd.ssidlen));
+ }
+ printf("\n");
}
- return (r);
+#endif
+ return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
}
static int
@@ -1362,28 +1396,9 @@ 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;
RSU_DPRINTF(sc, RSU_DEBUG_RESET,
@@ -1634,26 +1649,24 @@ rsu_rx_event(struct rsu_softc *sc, uint8
break;
case R92S_EVT_SURVEY_DONE:
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! */
- sc->sc_scan_pass = 1;
+ "%s: %s scan done, found %d BSS\n",
+ __func__, sc->sc_extra_scan ? "direct" : "broadcast",
+ le32toh(*(uint32_t *)buf));
+ if (sc->sc_extra_scan == 1) {
+ /* Send broadcast probe request. */
+ sc->sc_extra_scan = 0;
+ if (vap != NULL && rsu_site_survey(sc, NULL) != 0) {
+ RSU_UNLOCK(sc);
+ ieee80211_cancel_scan(vap);
+ RSU_LOCK(sc);
+ }
+ break;
+ }
+ if (vap != NULL) {
RSU_UNLOCK(sc);
- ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
+ ieee80211_scan_done(vap);
RSU_LOCK(sc);
- break;
}
- sc->sc_scan_pass = 0;
break;
case R92S_EVT_JOIN_BSS:
if (vap->iv_state == IEEE80211_S_AUTH)
@@ -2920,12 +2933,11 @@ rsu_init(struct rsu_softc *sc)
goto fail;
}
- sc->sc_scan_pass = 0;
+ sc->sc_extra_scan = 0;
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
/* 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 Sun Nov 27 09:20:58 2016 (r309209)
+++ head/sys/dev/usb/wlan/if_rsureg.h Sun Nov 27 12:03:34 2016 (r309210)
@@ -768,8 +768,8 @@ struct rsu_softc {
u_int sc_running:1,
sc_calibrating:1,
- sc_scanning:1,
- sc_scan_pass:1;
+ sc_active_scan:1,
+ sc_extra_scan:1;
u_int cut;
uint8_t sc_rftype;
int8_t sc_nrxstream;
More information about the svn-src-head
mailing list