LinuxKPI: 802.11: make sure dtim_period is set
When going from ASSOC to RUN LinuxKPI based wireless drivers have certian expectations written in various ways. I believe mac80211 waits to see a beacon before setting the vif to assoc (or the sta to AUTHORIZED). We have some comments in lkpi_update_dtim_tsf() for that. In practice we can filter out the beacons already and know when they came in as we count them but it is hard to split up the state machine and defer the work. So we make sure that dtim_period is set to at least 1 before calling the (*vif_cfg_change) after setting assoc to true; 0 is a reserved value according to the standards. We will update it once we see a beacon and in case the value differs from 1 shortly afterwards from the recv_mgmt callback. While iwlwifi seems to have coped with our initial implementation, rtw89 may hit a DIV 0 if dtim_period is 0 depending on how well the rx path races with our unlocking in assoc_to_run. Sponsored by: The FreeBSD Foundation MFC after: 3 days
This commit is contained in:
@@ -2013,12 +2013,23 @@ lkpi_update_dtim_tsf(struct ieee80211_vif *vif, struct ieee80211_node *ni,
|
||||
* make sure we do not do it on every beacon we still may
|
||||
* get so only do if something changed. vif->bss_conf.dtim_period
|
||||
* should be 0 as we start up (we also reset it on teardown).
|
||||
*
|
||||
* If we are assoc we need to make sure dtim_period is non-0.
|
||||
* 0 is a reserved value and drivers assume they can DIV by it.
|
||||
* In theory this means we need to wait for the first beacon
|
||||
* before we finalize the vif being assoc. In practise that
|
||||
* is harder until net80211 learns how to. Work around like
|
||||
* this for the moment.
|
||||
*/
|
||||
if (vif->cfg.assoc &&
|
||||
vif->bss_conf.dtim_period != ni->ni_dtim_period &&
|
||||
ni->ni_dtim_period > 0) {
|
||||
vif->bss_conf.dtim_period = ni->ni_dtim_period;
|
||||
bss_changed |= BSS_CHANGED_BEACON_INFO;
|
||||
if (vif->cfg.assoc) {
|
||||
if (vif->bss_conf.dtim_period != ni->ni_dtim_period &&
|
||||
ni->ni_dtim_period > 0) {
|
||||
vif->bss_conf.dtim_period = ni->ni_dtim_period;
|
||||
bss_changed |= BSS_CHANGED_BEACON_INFO;
|
||||
} else if (vif->bss_conf.dtim_period == 0) {
|
||||
vif->bss_conf.dtim_period = 1;
|
||||
bss_changed |= BSS_CHANGED_BEACON_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
vif->bss_conf.sync_dtim_count = ni->ni_dtim_count;
|
||||
|
||||
Reference in New Issue
Block a user