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);
> 
> 

Reply via email to