aboutsummaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches-r3776/321-bgscan_rssi_thresh.patch
blob: 7020305ea88b5e8c39b6d7bbb9dda9c884177326 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Add an optional background scanning threshold triggered by low rssi
(useful for passing updated scan results to the supplicant ahead of
time, before losing connectivity entirely)

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -655,6 +655,7 @@
 	IEEE80211_PARAM_MINRATE			= 84,	/* Minimum rate (by table index) */
 	IEEE80211_PARAM_PROTMODE_RSSI		= 85,	/* RSSI Threshold for enabling protection mode */
 	IEEE80211_PARAM_PROTMODE_TIMEOUT	= 86,	/* Timeout for expiring protection mode */
+	IEEE80211_PARAM_BGSCAN_THRESH		= 87,	/* bg scan rssi threshold */
 };
 
 #define	SIOCG80211STATS			(SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -92,6 +92,8 @@
 #define	IEEE80211_BGSCAN_IDLE_MIN	100	/* min idle time (ms) */
 #define	IEEE80211_BGSCAN_IDLE_DEFAULT	250	/* default idle time (ms) */
 
+#define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
+
 #define IEEE80211_COVERAGE_CLASS_MAX	31	/* max coverage class */
 #define IEEE80211_REGCLASSIDS_MAX	10	/* max regclass id list */
 
@@ -229,6 +231,9 @@
 	u_int8_t iv_nickname[IEEE80211_NWID_LEN];
 	u_int iv_bgscanidle;				/* bg scan idle threshold */
 	u_int iv_bgscanintvl;				/* bg scan min interval */
+	u_int iv_bgscanthr;					/* bg scan rssi threshold */
+	u_int iv_bgscantrintvl;				/* bg scan trigger interval */
+	unsigned long iv_bgscanthr_next;		/* last trigger for bgscan */
 	u_int iv_scanvalid;				/* scan cache valid threshold */
 	struct ieee80211_roam iv_roam;			/* sta-mode roaming state */
 
@@ -612,6 +617,7 @@
 #define IEEE80211_FEXT_SWBMISS		0x00000400	/* CONF: use software beacon timer */
 #define IEEE80211_FEXT_DROPUNENC_EAPOL	0x00000800	/* CONF: drop unencrypted eapol frames */
 #define IEEE80211_FEXT_APPIE_UPDATE	0x00001000	/* STATE: beacon APP IE updated */
+#define IEEE80211_FEXT_BGSCAN_THR	0x00002000	/* bgscan due to low rssi */
 
 #define IEEE80211_COM_UAPSD_ENABLE(_ic)		((_ic)->ic_flags_ext |= IEEE80211_FEXT_UAPSD)
 #define IEEE80211_COM_UAPSD_DISABLE(_ic)	((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_UAPSD)
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2778,6 +2778,9 @@
 		else
 			retv = EINVAL;
 		break;
+	case IEEE80211_PARAM_BGSCAN_THRESH:
+		vap->iv_bgscanthr = value;
+		break;
 	case IEEE80211_PARAM_MCAST_RATE:
 		/* units are in KILObits per second */
 		if (value >= 256 && value <= 54000)
@@ -3181,6 +3184,9 @@
 	case IEEE80211_PARAM_BGSCAN_INTERVAL:
 		param[0] = vap->iv_bgscanintvl / HZ;	/* seconds */
 		break;
+	case IEEE80211_PARAM_BGSCAN_THRESH:
+		param[0] = vap->iv_bgscanthr;	/* rssi */
+		break;
 	case IEEE80211_PARAM_MCAST_RATE:
 		param[0] = vap->iv_mcast_rate;	/* seconds */
 		break;
@@ -5704,6 +5710,10 @@
 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanintvl" },
 	{ IEEE80211_PARAM_BGSCAN_INTERVAL,
 	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanintvl" },
+	{ IEEE80211_PARAM_BGSCAN_THRESH,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanthr" },
+	{ IEEE80211_PARAM_BGSCAN_THRESH,
+	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanthr" },
 	{ IEEE80211_PARAM_MCAST_RATE,
 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcast_rate" },
 	{ IEEE80211_PARAM_MCAST_RATE,
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -2984,8 +2984,10 @@
 {
 	struct ieee80211com *ic = vap->iv_ic;
 
+	vap->iv_bgscantrintvl = (vap->iv_bgscantrintvl + 1) % 4;
 	return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
-		time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle));
+		(((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && !vap->iv_bgscantrintvl) ||
+			time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle)));
 }
 
 static __inline int
@@ -3229,6 +3231,23 @@
 			/* record tsf of last beacon */
 			memcpy(ni->ni_tstamp.data, scan.tstamp,
 				sizeof(ni->ni_tstamp));
+
+			/* When rssi is low, start doing bgscans more frequently to allow
+			 * the supplicant to make a better switching decision */
+			if ((rssi < vap->iv_bgscanthr) &&
+					(!vap->iv_bgscanthr_next ||
+						!time_before(jiffies, vap->iv_bgscanthr_next)) &&
+					!(ic->ic_flags & IEEE80211_F_SCAN)) {
+				int ret;
+
+				ic->ic_lastdata = 0;
+				ic->ic_lastscan = 0;
+				ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN_THR;
+				ret = ieee80211_bg_scan(vap);
+				if (ret)
+					vap->iv_bgscanthr_next = jiffies + msecs_to_jiffies(IEEE80211_BGSCAN_TRIGGER_INTVL * 1000);
+			}
+
 			if (ni->ni_intval != scan.bintval) {
 				IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
 						"beacon interval divergence: "
--- a/net80211/ieee80211_scan.c
+++ b/net80211/ieee80211_scan.c
@@ -793,7 +793,7 @@
 				ieee80211_sta_pwrsave(vap, 0);
 				if (ss->ss_next >= ss->ss_last) {
 					ieee80211_notify_scan_done(vap);
-					ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
+					ic->ic_flags_ext &= ~(IEEE80211_FEXT_BGSCAN|IEEE80211_FEXT_BGSCAN_THR);
 				}
 			}
 			SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;