From owner-svn-src-all@freebsd.org Sun Nov 27 12:03:36 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 624A9C58B1E; Sun, 27 Nov 2016 12:03:36 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2311A1141; Sun, 27 Nov 2016 12:03:36 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uARC3Zpf068131; Sun, 27 Nov 2016 12:03:35 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uARC3ZLe068129; Sun, 27 Nov 2016 12:03:35 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201611271203.uARC3ZLe068129@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Sun, 27 Nov 2016 12:03:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r309210 - head/sys/dev/usb/wlan X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Nov 2016 12:03:36 -0000 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;