On Thu, Dec 07, 2017 at 02:10:02PM +0100, Stefan Sperling wrote:
> I found a way to reproduce the "hangs" people have been reporting
> during 'ifconfig iwm0 scan'. The problem is actually quite trivial.
>
> To reproduce:
>
> 1) configure a network ID that does not exist around you
> 2) put the interface up
> 3) keep running ifconfig iwm0 scan; eventually ifconfig won't
> show results but just time out; and observe how no frames
> are received with: tcpdump -i iwm0 -y IEEE802_11_RADIO
>
> The problem is that iwm_newstate does not restart scans when a SCAN->SCAN
> transition happens and the firmware scan command is no longer busy.
Fixed diff: The previous diff accidentally started a new scan even
while the firmware was still busy scanning.
Index: if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.217
diff -u -p -r1.217 if_iwm.c
--- if_iwm.c 26 Oct 2017 15:00:28 -0000 1.217
+++ if_iwm.c 7 Dec 2017 13:20:57 -0000
@@ -5986,17 +5986,27 @@ iwm_newstate_task(void *psc)
ieee80211_state_name[ostate],
ieee80211_state_name[nstate]));
- if (nstate == ostate || (sc->sc_flags & IWM_FLAG_SHUTDOWN)) {
- /* No-op state change or iwm_stop() is waiting for us. */
+ if (sc->sc_flags & IWM_FLAG_SHUTDOWN) {
+ /* iwm_stop() is waiting for us. */
refcnt_rele_wake(&sc->task_refs);
splx(s);
return;
}
- if (ostate == IEEE80211_S_SCAN)
- iwm_led_blink_stop(sc);
+ if (ostate == IEEE80211_S_SCAN) {
+ if (nstate == ostate) {
+ if (sc->sc_flags & IWM_FLAG_SCANNING) {
+ refcnt_rele_wake(&sc->task_refs);
+ splx(s);
+ return;
+ }
+ /* Firmware is no longer scanning. Do another scan. */
+ goto next_scan;
+ } else
+ iwm_led_blink_stop(sc);
+ }
- if (nstate < ostate) {
+ if (nstate <= ostate) {
switch (ostate) {
case IEEE80211_S_RUN:
err = iwm_run_stop(sc);
@@ -6035,6 +6045,7 @@ iwm_newstate_task(void *psc)
break;
case IEEE80211_S_SCAN:
+next_scan:
err = iwm_scan(sc);
if (err)
break;