freebsd-skq/sys/net80211
Adrian Chadd 1de34f860e Update ieee80211_sta_tim_notify() to do double duty - handle STA sleep
to awake transition as well as handle waking up a VAP in STA powersave
mode if it's in bgscan.

This was a reasonably hairy bug to try and figure out and it became
more obvious because of stuff I've done.

Specifically:

* a NIC would go into bgscan mode - either because of a bgscan timer
  or wpa_supplicant asked it to;
* the AP would indicate there's traffic for the STA by setting the TIM
  bitmap bit for it;
* mindwell would be met during scan, so it'd wake up and break out of
  the scan loop in scan_task(), but
* because the scan wasn't completed, it wouldn't bring the VAP out of
  STA mode powersave (so it wouldn't tell the AP about it and it would
  block VAP TX);
* .. but because we kept seeing the TIM bit set, ic->ic_lastdata was
  being constantly updated, and ..
* bgscancont() would thus never say "yes we can continue a bgscan"
  so the bgscan would hang and never make progress.

Now, I do see this particular state occur on iwn(4) - /however/ -
this NIC has the firmware call ieee80211_scan_next() once the firmware
scan for that channel has completed.  This has the effect of moving
the scan along to the next channel.  I do see the debug that I'm adding
where we see a beacon with a TIM bit set whilst we're in bgscan, so
the condition about waking up to receive traffic is triggering.
It just won't cause a hang.

For other NICs - all of the USB ones and at least ath(4) -
ieee80211_scan_next() / ieee80211_scan_done() isn't called.
So it relies upon the mindwell timer, the beacon receive and the
beacon / probe response -> ieee80211_add_scan() to move along
the scan state.

In the above case, mindwell triggered, there's no beacons triggering
the scan_add code to move things along, and we weren't waking things
up when seeing the TIM set for us.  So it just hung until the interface
was dropped.

So, the short-term fix here is to do what the comment in scan_task()
says - if we are in bgscan mode and we see our TIM bit set, just wake
up the VAP.  If it's already awake then it's a nop.  If we're awake
then we transition to awake and handle the traffic.  Once there's no
TX or RX traffic going on, ic->ic_lastdata won't be updated anymore
and bgscancont() will continue.

This was triggered more often after my initial SLEEP state handling
for software sleep states - because now I update ic->ic_lastdata
upon seeing a TIM bit set, not just the RX of the subsequent traffic.
That's needed so the thing doesn't ping-pong up and down between
seeing the TIM bit set, sending the "I'm awake" NULL data frame, and
starting to receive data from the AP.

I'd like to subsequently split ic_lastdata into two - one for TX and
one for RX - so it becomes easier to use the correct one (or both!)
when making decisions like whether to scan, go to sleep, etc.

I'd appreciate this getting some further testing.

Tested:

* rsu(4), STA mode, bgscan on
* iwn(4), STA mode, bgscan on
2014-12-21 04:58:45 +00:00
..
_ieee80211.h
ieee80211_acl.c
ieee80211_action.c
ieee80211_action.h
ieee80211_adhoc.c Mechanically convert to if_inc_counter(). 2014-09-19 09:20:55 +00:00
ieee80211_adhoc.h
ieee80211_ageq.c
ieee80211_ageq.h
ieee80211_alq.c
ieee80211_alq.h
ieee80211_amrr.c After much toying around with this AMRR initial rate stuff, 2014-08-20 09:10:03 +00:00
ieee80211_amrr.h
ieee80211_crypto_ccmp.c
ieee80211_crypto_none.c
ieee80211_crypto_tkip.c
ieee80211_crypto_wep.c
ieee80211_crypto.c
ieee80211_crypto.h
ieee80211_ddb.c
ieee80211_dfs.c
ieee80211_dfs.h
ieee80211_freebsd.c
ieee80211_freebsd.h
ieee80211_hostap.c Mechanically convert to if_inc_counter(). 2014-09-19 09:20:55 +00:00
ieee80211_hostap.h
ieee80211_ht.c Fix multiple incorrect SYSCTL arguments in the kernel: 2014-10-21 07:31:21 +00:00
ieee80211_ht.h
ieee80211_hwmp.c Fix multiple incorrect SYSCTL arguments in the kernel: 2014-10-21 07:31:21 +00:00
ieee80211_input.c Mechanically convert to if_inc_counter(). 2014-09-19 09:20:55 +00:00
ieee80211_input.h
ieee80211_ioctl.c Use logical rather than bitwise OR in if() expression. 2014-04-26 23:22:49 +00:00
ieee80211_ioctl.h
ieee80211_mesh.c Fix multiple incorrect SYSCTL arguments in the kernel: 2014-10-21 07:31:21 +00:00
ieee80211_mesh.h
ieee80211_monitor.c Mechanically convert to if_inc_counter(). 2014-09-19 09:20:55 +00:00
ieee80211_monitor.h
ieee80211_node.c
ieee80211_node.h
ieee80211_output.c Make ieee80211_add_ssid() public. 2014-12-19 01:39:58 +00:00
ieee80211_phy.c
ieee80211_phy.h
ieee80211_power.c Update ieee80211_sta_tim_notify() to do double duty - handle STA sleep 2014-12-21 04:58:45 +00:00
ieee80211_power.h Begin fleshing out support for net80211 provided (legacy) sleep management. 2014-04-24 01:39:53 +00:00
ieee80211_proto.c
ieee80211_proto.h Make ieee80211_add_ssid() public. 2014-12-19 01:39:58 +00:00
ieee80211_radiotap.c
ieee80211_radiotap.h
ieee80211_ratectl_none.c
ieee80211_ratectl.c
ieee80211_ratectl.h
ieee80211_regdomain.c
ieee80211_regdomain.h
ieee80211_rssadapt.c
ieee80211_rssadapt.h
ieee80211_scan_sta.c Fix the scan handling for 11b->11g upgrades in a world where, well, 2014-12-18 05:17:18 +00:00
ieee80211_scan.c Add more debugging to try and track down this scan hang nonsense. 2014-12-21 01:15:55 +00:00
ieee80211_scan.h
ieee80211_sta.c Break out the unicast/multicast TIM bit setting into "set something 2014-12-21 04:48:54 +00:00
ieee80211_sta.h
ieee80211_superg.c Fix multiple incorrect SYSCTL arguments in the kernel: 2014-10-21 07:31:21 +00:00
ieee80211_superg.h
ieee80211_tdma.c
ieee80211_tdma.h
ieee80211_var.h Add a capability to indicate that the net80211 stack should be doing 2014-04-24 01:28:39 +00:00
ieee80211_wds.c Mechanically convert to if_inc_counter(). 2014-09-19 09:20:55 +00:00
ieee80211_wds.h
ieee80211_xauth.c
ieee80211.c Mechanically convert to if_inc_counter(). 2014-09-19 09:20:55 +00:00
ieee80211.h