On Wed, Jan 31, 2018 at 01:25:10PM +0100, Stefan Sperling wrote:
>
> If iwn(4) is in associated state (status: active), and I run:
>
> ifconfig iwn0 scan
>
> it loses link (status: no network) and never comes back while the
> LED keeps blinking. I need to run 'ifconfig iwn0 down' to recover.
I'm getting the same problem.
> What happens is the driver goes to SCAN state and sends a scan
> command to the firmware and waits for a STOP_SCAN response.
> This happens while the firmware is in associated state, with a
> scan command which does *not* run a background scan. It seems the
> firmware doesn't like this and never signals STOP_SCAN, so the
> driver remains in SCAN state until the interface gets reset.
>
> I can fix this problem by making the driver move the firmware out
> of associated state during RUN->SCAN transitions. For completeness
> we can do the same for RUN->{ASSOC,AUTH} and AUTH->ASSOC. i.e. always
> keep the firmware's association state in sync with the driver's state
> machine. The firmware should only be associated in RUN state.
>
> The diff below does that, and also adds support for SCAN->SCAN
> transitions to the state machine (which are a no-op in this driver).
>
> This seems to be working well here with:
> iwn0 at pci3 dev 0 function 0 "Intel Centrino Advanced-N 6200" rev 0x35: msi,
> MIMO 2T2R, MoW, address xx:xx:xx:xx:xx:xx
>
> OK to commit? Does anybody else want to test this beforehand?
Your diff works for me as well:
iwn0 at pci2 dev 0 function 0 "Intel Wireless WiFi Link 4965" rev 0x61: msi,
MIMO 2T3R, MoW1, address 00:1d:e0:b3:e6:c1
Thanks. ok kevlo@
> Index: if_iwn.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
> retrieving revision 1.198
> diff -u -p -r1.198 if_iwn.c
> --- if_iwn.c 9 Jan 2018 10:00:12 -0000 1.198
> +++ if_iwn.c 31 Jan 2018 12:13:41 -0000
> @@ -1772,6 +1772,25 @@ iwn_newstate(struct ieee80211com *ic, en
> iwn_scan_abort(sc);
> }
>
> + if (ic->ic_state == IEEE80211_S_SCAN) {
> + if (nstate == IEEE80211_S_SCAN)
> + return 0;
> + /* Turn LED off when leaving scan state. */
> + iwn_set_led(sc, IWN_LED_LINK, 1, 0);
> + }
> +
> + if (ic->ic_state >= IEEE80211_S_ASSOC &&
> + nstate <= IEEE80211_S_ASSOC) {
> + /* Reset state to handle re- and disassociations. */
> + sc->rxon.associd = 0;
> + sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
> + sc->calib.state = IWN_CALIB_STATE_INIT;
> + error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
> + if (error != 0)
> + printf("%s: RXON command failed\n",
> + sc->sc_dev.dv_xname);
> + }
> +
> switch (nstate) {
> case IEEE80211_S_SCAN:
> /* Make the link LED blink while we're scanning. */
> @@ -1790,11 +1809,6 @@ iwn_newstate(struct ieee80211com *ic, en
> break;
> /* FALLTHROUGH */
> case IEEE80211_S_AUTH:
> - /* Reset state to handle reassociations correctly. */
> - sc->rxon.associd = 0;
> - sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
> - sc->calib.state = IWN_CALIB_STATE_INIT;
> -
> if ((error = iwn_auth(sc, arg)) != 0) {
> printf("%s: could not move to auth state\n",
> sc->sc_dev.dv_xname);
>
>