Improve the beacon miss handling. Instead of just dropping the connection, send a directed probe request to the AP to see if it's still responding. Schedule a software beacon miss timer in this case, which adds a timeout for the APs probe response. Signed-off-by: Felix Fietkau --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c @@ -3400,12 +3400,17 @@ ieee80211_recv_mgmt(struct ieee80211vap } /* WDS/Repeater: re-schedule software beacon timer for - * STA. */ - if ((vap->iv_state == IEEE80211_S_RUN) && - (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) { - mod_timer(&vap->iv_swbmiss, + * STA. Reset consecutive bmiss counter as well */ + IEEE80211_LOCK_IRQ(ic); + if (vap->iv_state == IEEE80211_S_RUN) { + vap->iv_bmiss_count = 0; + if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) + mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period); + else + del_timer(&vap->iv_swbmiss); } + IEEE80211_UNLOCK_IRQ(ic); /* If scanning, pass the info to the scan module. * Otherwise, check if it's the right time to do --- a/net80211/ieee80211_proto.c +++ b/net80211/ieee80211_proto.c @@ -1209,6 +1209,8 @@ ieee80211_beacon_miss(struct ieee80211co } /* XXX locking */ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + int count; + IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, "%s\n", "beacon miss"); @@ -1221,6 +1223,29 @@ ieee80211_beacon_miss(struct ieee80211co if (vap->iv_opmode != IEEE80211_M_STA || vap->iv_state != IEEE80211_S_RUN) continue; + + IEEE80211_LOCK_IRQ(ic); + count = vap->iv_bmiss_count++; + if (count) { + /* if the counter was already above zero, reset it + * here, since we're going to do the bmiss handling + * in any case */ + vap->iv_bmiss_count = 0; + } else { + /* schedule the software beacon miss timer, it will be + * cancelled, if the probe request is acked */ + mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period); + } + IEEE80211_UNLOCK_IRQ(ic); + + if (!count) { + ieee80211_send_probereq(vap->iv_bss, vap->iv_myaddr, + vap->iv_bss->ni_bssid, vap->iv_bss->ni_bssid, + vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen, + NULL, 0); + continue; + } + if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { #ifdef ATH_SUPERG_DYNTURBO /* @@ -1621,14 +1646,14 @@ __ieee80211_newstate(struct ieee80211vap } /* WDS/Repeater: Start software beacon timer for STA */ + vap->iv_swbmiss.function = ieee80211_sta_swbmiss; + vap->iv_swbmiss.data = (unsigned long) vap; + vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES( + vap->iv_ic->ic_bmissthreshold * ni->ni_intval); + if (ostate != IEEE80211_S_RUN && (vap->iv_opmode == IEEE80211_M_STA && vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) { - vap->iv_swbmiss.function = ieee80211_sta_swbmiss; - vap->iv_swbmiss.data = (unsigned long) vap; - vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES( - vap->iv_ic->ic_bmissthreshold * ni->ni_intval); - mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period); } --- a/net80211/ieee80211_var.h +++ b/net80211/ieee80211_var.h @@ -283,6 +283,7 @@ struct ieee80211vap { struct timer_list iv_swbmiss; /* software beacon miss timer */ u_int16_t iv_swbmiss_period; /* software beacon miss timer period */ + u_int16_t iv_bmiss_count; /* consecutive beacon miss counter */ struct ieee80211_nsparams iv_nsparams; /* new state parameters for tasklet for stajoin1 */ struct IEEE80211_TQ_STRUCT iv_stajoin1tq; /* tasklet for newstate action called from stajoin1tq */ unsigned int iv_nsdone; /* Done with scheduled newstate tasklet */