From 09bcffddf168155a2ec60a99d4cface588397ceb Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 12 Jul 2008 22:24:36 +0000
Subject: madwifi: improve beacon miss handling to increase the reliability of
 STA mode links

SVN-Revision: 11798
---
 package/madwifi/patches/361-bmiss_handling.patch | 102 +++++++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 package/madwifi/patches/361-bmiss_handling.patch

diff --git a/package/madwifi/patches/361-bmiss_handling.patch b/package/madwifi/patches/361-bmiss_handling.patch
new file mode 100644
index 0000000000..814a916dd0
--- /dev/null
+++ b/package/madwifi/patches/361-bmiss_handling.patch
@@ -0,0 +1,102 @@
+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 <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3398,12 +3398,17 @@
+ 			}
+ 
+ 			/* 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 @@
+ 	}
+ 	/* 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 @@
+ 		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
+ 			/* 
+@@ -1617,14 +1642,14 @@
+ 		}
+ 
+ 		/* 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
+@@ -282,6 +282,7 @@
+ 
+ 	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 */
-- 
cgit v1.2.3