]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/mac80211-add-direct-probe.patch
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / mac80211-add-direct-probe.patch
1 From: Ron Rindjunsky <ron.rindjunsky@intel.com>
2 Date: Sat, 9 Aug 2008 03:02:19 +0300
3 Subject: [PATCH] mac80211: add direct probe before association
4 Patch-mainline: 2.6.28-rc1
5 References: bnc#461889
6
7 This patch adds a direct probe request as first step in the association
8 flow if data we have is not up to date. Motivation of this step is to make
9 sure that the bss information we have is correct, since last scan could
10 have been done a while ago, and beacons do not fully answer this need as
11 there are potential differences between them and probe responses (e.g.
12 WMM parameter element)
13
14 Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com>
15 Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
16 Signed-off-by: John W. Linville <linville@tuxdriver.com>
17
18 Modified not to break kABI: auth_tries is overriden to also mean
19 direct_probe_tries, last_probe_resp is moved to the end of the
20 ieee80211_sta_bss structure.
21
22 Signed-off-by: Jiri Benc <jbenc@suse.cz>
23
24 ---
25 net/mac80211/ieee80211_i.h | 10 +++++
26 net/mac80211/mlme.c | 79 ++++++++++++++++++++++++++++++++++++++-------
27 2 files changed, 77 insertions(+), 12 deletions(-)
28
29 --- linux-2.6.27.orig/net/mac80211/ieee80211_i.h
30 +++ linux-2.6.27/net/mac80211/ieee80211_i.h
31 @@ -117,6 +117,10 @@ struct ieee80211_sta_bss {
32 * otherwise, you probably don't want to use them. */
33 int has_erp_value;
34 u8 erp_value;
35 +
36 +#ifndef __GENKSYMS__
37 + unsigned long last_probe_resp;
38 +#endif
39 };
40
41 static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
42 @@ -310,6 +314,9 @@ struct ieee80211_if_sta {
43 IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
44 IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
45 IEEE80211_MESH_UP
46 +#ifndef __GENKSYMS__
47 + , IEEE80211_DIRECT_PROBE
48 +#endif
49 } state;
50 size_t ssid_len;
51 u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
52 @@ -363,6 +370,7 @@ struct ieee80211_if_sta {
53 #define IEEE80211_STA_REQ_SCAN 0
54 #define IEEE80211_STA_REQ_AUTH 1
55 #define IEEE80211_STA_REQ_RUN 2
56 +#define IEEE80211_STA_REQ_DIRECT_PROBE 3
57
58 #define IEEE80211_AUTH_ALG_OPEN BIT(0)
59 #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
60 --- linux-2.6.27.orig/net/mac80211/mlme.c
61 +++ linux-2.6.27/net/mac80211/mlme.c
62 @@ -658,6 +658,36 @@ static void ieee80211_send_auth(struct n
63 ieee80211_sta_tx(dev, skb, encrypt);
64 }
65
66 +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
67 + struct ieee80211_if_sta *ifsta)
68 +{
69 + DECLARE_MAC_BUF(mac);
70 +
71 + ifsta->auth_tries++; /* used as direct_probe_tries */
72 + if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
73 + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n",
74 + sdata->dev->name, print_mac(mac, ifsta->bssid));
75 + ifsta->state = IEEE80211_DISABLED;
76 + return;
77 + }
78 +
79 + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n",
80 + sdata->dev->name, print_mac(mac, ifsta->bssid),
81 + ifsta->auth_tries);
82 +
83 + ifsta->state = IEEE80211_DIRECT_PROBE;
84 +
85 + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request);
86 +
87 + /* Direct probe is sent to broadcast address as some APs
88 + * will not answer to direct packet in unassociated state.
89 + */
90 + ieee80211_send_probe_req(sdata->dev, NULL,
91 + ifsta->ssid, ifsta->ssid_len);
92 +
93 + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
94 +}
95 +
96
97 static void ieee80211_authenticate(struct net_device *dev,
98 struct ieee80211_if_sta *ifsta)
99 @@ -1958,7 +1988,7 @@ static void ieee80211_rx_mgmt_deauth(str
100 if (ifsta->state == IEEE80211_AUTHENTICATE ||
101 ifsta->state == IEEE80211_ASSOCIATE ||
102 ifsta->state == IEEE80211_ASSOCIATED) {
103 - ifsta->state = IEEE80211_AUTHENTICATE;
104 + ifsta->state = IEEE80211_DIRECT_PROBE;
105 mod_timer(&ifsta->timer, jiffies +
106 IEEE80211_RETRY_AUTH_INTERVAL);
107 }
108 @@ -2559,8 +2589,7 @@ static void ieee80211_rx_bss_info(struct
109 struct ieee80211_mgmt *mgmt,
110 size_t len,
111 struct ieee80211_rx_status *rx_status,
112 - struct ieee802_11_elems *elems,
113 - int beacon)
114 + struct ieee802_11_elems *elems)
115 {
116 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
117 int freq, clen;
118 @@ -2569,6 +2598,7 @@ static void ieee80211_rx_bss_info(struct
119 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
120 u64 beacon_timestamp, rx_timestamp;
121 struct ieee80211_channel *channel;
122 + bool beacon = ieee80211_is_beacon(mgmt->frame_control);
123 DECLARE_MAC_BUF(mac);
124 DECLARE_MAC_BUF(mac2);
125
126 @@ -2728,15 +2758,14 @@ static void ieee80211_rx_bss_info(struct
127 bss->signal = rx_status->signal;
128 bss->noise = rx_status->noise;
129 bss->qual = rx_status->qual;
130 - if (!beacon && !bss->probe_resp)
131 - bss->probe_resp = true;
132 -
133 + if (!beacon)
134 + bss->last_probe_resp = jiffies;
135 /*
136 * In STA mode, the remaining parameters should not be overridden
137 * by beacons because they're not necessarily accurate there.
138 */
139 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
140 - bss->probe_resp && beacon) {
141 + bss->last_probe_resp && beacon) {
142 ieee80211_rx_bss_put(local, bss);
143 return;
144 }
145 @@ -2891,6 +2920,8 @@ static void ieee80211_rx_mgmt_probe_resp
146 {
147 size_t baselen;
148 struct ieee802_11_elems elems;
149 + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
150 + struct ieee80211_if_sta *ifsta = &sdata->u.sta;
151
152 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
153 if (baselen > len)
154 @@ -2899,7 +2930,17 @@ static void ieee80211_rx_mgmt_probe_resp
155 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
156 &elems);
157
158 - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0);
159 + ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems);
160 +
161 + /* direct probe may be part of the association flow */
162 + if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
163 + &ifsta->request)) {
164 + printk(KERN_DEBUG "%s direct probe responded\n",
165 + sdata->dev->name);
166 + ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */
167 + ieee80211_authenticate(dev, ifsta);
168 + }
169 +
170 }
171
172
173 @@ -2923,7 +2964,7 @@ static void ieee80211_rx_mgmt_beacon(str
174
175 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
176
177 - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1);
178 + ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems);
179
180 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
181 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
182 @@ -3361,7 +3402,8 @@ void ieee80211_sta_work(struct work_stru
183 mesh_path_start_discovery(dev);
184 #endif
185
186 - if (ifsta->state != IEEE80211_AUTHENTICATE &&
187 + if (ifsta->state != IEEE80211_DIRECT_PROBE &&
188 + ifsta->state != IEEE80211_AUTHENTICATE &&
189 ifsta->state != IEEE80211_ASSOCIATE &&
190 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
191 if (ifsta->scan_ssid_len)
192 @@ -3381,6 +3423,10 @@ void ieee80211_sta_work(struct work_stru
193 switch (ifsta->state) {
194 case IEEE80211_DISABLED:
195 break;
196 + case IEEE80211_DIRECT_PROBE:
197 + ieee80211_direct_probe(sdata, ifsta);
198 + break;
199 +
200 case IEEE80211_AUTHENTICATE:
201 ieee80211_authenticate(dev, ifsta);
202 break;
203 @@ -3541,8 +3587,18 @@ static int ieee80211_sta_config_auth(str
204 selected->ssid_len);
205 ieee80211_sta_set_bssid(dev, selected->bssid);
206 ieee80211_sta_def_wmm_params(dev, selected, 0);
207 +
208 + /* Send out direct probe if no probe resp was received or
209 + * the one we have is outdated
210 + */
211 + if (!selected->last_probe_resp ||
212 + time_after(jiffies, selected->last_probe_resp
213 + + IEEE80211_SCAN_RESULT_EXPIRE))
214 + ifsta->state = IEEE80211_DIRECT_PROBE;
215 + else
216 + ifsta->state = IEEE80211_AUTHENTICATE;
217 +
218 ieee80211_rx_bss_put(local, selected);
219 - ifsta->state = IEEE80211_AUTHENTICATE;
220 ieee80211_sta_reset_auth(dev, ifsta);
221 return 0;
222 } else {
223 @@ -3553,6 +3609,7 @@ static int ieee80211_sta_config_auth(str
224 ieee80211_sta_start_scan(dev, ifsta->ssid,
225 ifsta->ssid_len);
226 ifsta->state = IEEE80211_AUTHENTICATE;
227 + ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */
228 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
229 } else
230 ifsta->state = IEEE80211_DISABLED;