aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c42
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c16
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c40
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c18
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c6
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c10
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c37
8 files changed, 143 insertions, 27 deletions
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f3427be6..f2a27cc6ecb1 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
1config IEEE80211_SOFTMAC 1config IEEE80211_SOFTMAC
2 tristate "Software MAC add-on to the IEEE 802.11 networking stack" 2 tristate "Software MAC add-on to the IEEE 802.11 networking stack"
3 depends on IEEE80211 && EXPERIMENTAL 3 depends on IEEE80211 && EXPERIMENTAL
4 select WIRELESS_EXT
4 ---help--- 5 ---help---
5 This option enables the hardware independent software MAC addon 6 This option enables the hardware independent software MAC addon
6 for the IEEE 802.11 networking stack. 7 for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78dfa4..57ea9f6f465c 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
51 spin_lock_irqsave(&mac->lock, flags); 51 spin_lock_irqsave(&mac->lock, flags);
52 mac->associnfo.associating = 1; 52 mac->associnfo.associating = 1;
53 mac->associated = 0; /* just to make sure */ 53 mac->associated = 0; /* just to make sure */
54 spin_unlock_irqrestore(&mac->lock, flags);
55 54
56 /* Set a timer for timeout */ 55 /* Set a timer for timeout */
57 /* FIXME: make timeout configurable */ 56 /* FIXME: make timeout configurable */
58 schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); 57 if (likely(mac->running))
58 schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
59 spin_unlock_irqrestore(&mac->lock, flags);
59} 60}
60 61
61void 62void
@@ -101,6 +102,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
101 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ 102 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
102 mac->associated = 0; 103 mac->associated = 0;
103 mac->associnfo.associating = 0; 104 mac->associnfo.associating = 0;
105 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
104 spin_unlock_irqrestore(&mac->lock, flags); 106 spin_unlock_irqrestore(&mac->lock, flags);
105} 107}
106 108
@@ -143,6 +145,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
143 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) 145 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
144 return 0; 146 return 0;
145 147
148 /* assume that users know what they're doing ...
149 * (note we don't let them select a net we're incompatible with) */
150 if (mac->associnfo.bssfixed) {
151 return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
152 }
153
146 /* if 'ANY' network requested, take any that doesn't have privacy enabled */ 154 /* if 'ANY' network requested, take any that doesn't have privacy enabled */
147 if (mac->associnfo.req_essid.len == 0 155 if (mac->associnfo.req_essid.len == 0
148 && !(net->capability & WLAN_CAPABILITY_PRIVACY)) 156 && !(net->capability & WLAN_CAPABILITY_PRIVACY))
@@ -175,7 +183,7 @@ ieee80211softmac_assoc_work(void *d)
175 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); 183 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
176 184
177 /* try to find the requested network in our list, if we found one already */ 185 /* try to find the requested network in our list, if we found one already */
178 if (mac->associnfo.bssvalid) 186 if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
179 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 187 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
180 188
181 /* Search the ieee80211 networks for this network if we didn't find it by bssid, 189 /* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -240,19 +248,25 @@ ieee80211softmac_assoc_work(void *d)
240 if (ieee80211softmac_start_scan(mac)) 248 if (ieee80211softmac_start_scan(mac))
241 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); 249 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
242 return; 250 return;
243 } 251 } else {
244 else {
245 spin_lock_irqsave(&mac->lock, flags); 252 spin_lock_irqsave(&mac->lock, flags);
246 mac->associnfo.associating = 0; 253 mac->associnfo.associating = 0;
247 mac->associated = 0; 254 mac->associated = 0;
248 spin_unlock_irqrestore(&mac->lock, flags); 255 spin_unlock_irqrestore(&mac->lock, flags);
249 256
250 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); 257 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
258 /* reset the retry counter for the next user request since we
259 * break out and don't reschedule ourselves after this point. */
260 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
251 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); 261 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
252 return; 262 return;
253 } 263 }
254 } 264 }
255 265
266 /* reset the retry counter for the next user request since we
267 * now found a net and will try to associate to it, but not
268 * schedule this function again. */
269 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
256 mac->associnfo.bssvalid = 1; 270 mac->associnfo.bssvalid = 1;
257 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); 271 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
258 /* copy the ESSID for displaying it */ 272 /* copy the ESSID for displaying it */
@@ -306,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
306 u16 status = le16_to_cpup(&resp->status); 320 u16 status = le16_to_cpup(&resp->status);
307 struct ieee80211softmac_network *network = NULL; 321 struct ieee80211softmac_network *network = NULL;
308 unsigned long flags; 322 unsigned long flags;
323
324 if (unlikely(!mac->running))
325 return -ENODEV;
309 326
310 spin_lock_irqsave(&mac->lock, flags); 327 spin_lock_irqsave(&mac->lock, flags);
311 328
@@ -364,15 +381,22 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
364{ 381{
365 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 382 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
366 unsigned long flags; 383 unsigned long flags;
384
385 if (unlikely(!mac->running))
386 return -ENODEV;
387
367 if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) 388 if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
368 return 0; 389 return 0;
390
369 if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) 391 if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
370 return 0; 392 return 0;
393
371 dprintk(KERN_INFO PFX "got disassoc frame\n"); 394 dprintk(KERN_INFO PFX "got disassoc frame\n");
372 netif_carrier_off(dev); 395 netif_carrier_off(dev);
373 spin_lock_irqsave(&mac->lock, flags); 396 spin_lock_irqsave(&mac->lock, flags);
374 mac->associnfo.bssvalid = 0; 397 mac->associnfo.bssvalid = 0;
375 mac->associated = 0; 398 mac->associated = 0;
399 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
376 schedule_work(&mac->associnfo.work); 400 schedule_work(&mac->associnfo.work);
377 spin_unlock_irqrestore(&mac->lock, flags); 401 spin_unlock_irqrestore(&mac->lock, flags);
378 402
@@ -386,11 +410,15 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
386 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 410 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
387 struct ieee80211softmac_network *network; 411 struct ieee80211softmac_network *network;
388 412
413 if (unlikely(!mac->running))
414 return -ENODEV;
415
389 network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); 416 network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
390 if (!network) { 417 if (!network) {
391 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); 418 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
392 return 0; 419 return 0;
393 } 420 }
394 ieee80211softmac_assoc(mac, network); 421 schedule_work(&mac->associnfo.work);
422
395 return 0; 423 return 0;
396} 424}
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 9a0eac6c61eb..06e332624665 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data)
86 86
87 /* Lock and set flags */ 87 /* Lock and set flags */
88 spin_lock_irqsave(&mac->lock, flags); 88 spin_lock_irqsave(&mac->lock, flags);
89 if (unlikely(!mac->running)) {
90 /* Prevent reschedule on workqueue flush */
91 spin_unlock_irqrestore(&mac->lock, flags);
92 return;
93 }
89 net->authenticated = 0; 94 net->authenticated = 0;
90 net->authenticating = 1; 95 net->authenticating = 1;
91 /* add a timeout call so we eventually give up waiting for an auth reply */ 96 /* add a timeout call so we eventually give up waiting for an auth reply */
@@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
124 unsigned long flags; 129 unsigned long flags;
125 u8 * data; 130 u8 * data;
126 131
132 if (unlikely(!mac->running))
133 return -ENODEV;
134
127 /* Find correct auth queue item */ 135 /* Find correct auth queue item */
128 spin_lock_irqsave(&mac->lock, flags); 136 spin_lock_irqsave(&mac->lock, flags);
129 list_for_each(list_ptr, &mac->auth_queue) { 137 list_for_each(list_ptr, &mac->auth_queue) {
@@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
298 306
299 /* can't transmit data right now... */ 307 /* can't transmit data right now... */
300 netif_carrier_off(mac->dev); 308 netif_carrier_off(mac->dev);
301 /* let's try to re-associate */
302 schedule_work(&mac->associnfo.work);
303 spin_unlock_irqrestore(&mac->lock, flags); 309 spin_unlock_irqrestore(&mac->lock, flags);
304} 310}
305 311
@@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
338 struct ieee80211softmac_network *net = NULL; 344 struct ieee80211softmac_network *net = NULL;
339 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 345 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
340 346
347 if (unlikely(!mac->running))
348 return -ENODEV;
349
341 if (!deauth) { 350 if (!deauth) {
342 dprintk("deauth without deauth packet. eek!\n"); 351 dprintk("deauth without deauth packet. eek!\n");
343 return 0; 352 return 0;
@@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
360 } 369 }
361 370
362 ieee80211softmac_deauth_from_net(mac, net); 371 ieee80211softmac_deauth_from_net(mac, net);
372
373 /* let's try to re-associate */
374 schedule_work(&mac->associnfo.work);
363 return 0; 375 return 0;
364} 376}
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbda1e4c..8cc8f3f0f8e7 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
67 "authenticating failed", 67 "authenticating failed",
68 "authenticating timed out", 68 "authenticating timed out",
69 "associating failed because no suitable network was found", 69 "associating failed because no suitable network was found",
70 "disassociated",
70}; 71};
71 72
72 73
@@ -128,13 +129,42 @@ void
128ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) 129ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
129{ 130{
130 struct ieee80211softmac_event *eventptr, *tmp; 131 struct ieee80211softmac_event *eventptr, *tmp;
131 union iwreq_data wrqu; 132 struct ieee80211softmac_network *network;
132 char *msg;
133 133
134 if (event >= 0) { 134 if (event >= 0) {
135 msg = event_descriptions[event]; 135 union iwreq_data wrqu;
136 wrqu.data.length = strlen(msg); 136 int we_event;
137 wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); 137 char *msg = NULL;
138
139 switch(event) {
140 case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
141 network = (struct ieee80211softmac_network *)event_ctx;
142 wrqu.data.length = 0;
143 wrqu.data.flags = 0;
144 memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
145 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
146 we_event = SIOCGIWAP;
147 break;
148 case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
149 wrqu.data.length = 0;
150 wrqu.data.flags = 0;
151 memset(&wrqu, '\0', sizeof (union iwreq_data));
152 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
153 we_event = SIOCGIWAP;
154 break;
155 case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
156 wrqu.data.length = 0;
157 wrqu.data.flags = 0;
158 memset(&wrqu, '\0', sizeof (union iwreq_data));
159 we_event = SIOCGIWSCAN;
160 break;
161 default:
162 msg = event_descriptions[event];
163 wrqu.data.length = strlen(msg);
164 we_event = IWEVCUSTOM;
165 break;
166 }
167 wireless_send_event(mac->dev, we_event, &wrqu, msg);
138 } 168 }
139 169
140 if (!list_empty(&mac->events)) 170 if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51dbb412..cc6cd56c85b1 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); 180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
181 181
182 /* Fill in capability Info */ 182 /* Fill in capability Info */
183 (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? 183 switch (mac->ieee->iw_mode) {
184 cpu_to_le16(WLAN_CAPABILITY_ESS) : 184 case IW_MODE_INFRA:
185 cpu_to_le16(WLAN_CAPABILITY_IBSS); 185 (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
186 break;
187 case IW_MODE_ADHOC:
188 (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
189 break;
190 case IW_MODE_AUTO:
191 (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
192 break;
193 default:
194 /* bleh. we don't ever go to these modes */
195 printk(KERN_ERR PFX "invalid iw_mode!\n");
196 break;
197 }
186 /* Need to add this 198 /* Need to add this
187 (*pkt)->capability |= mac->ieee->short_slot ? 199 (*pkt)->capability |= mac->ieee->short_slot ?
188 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; 200 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 60f06a31f0d1..6252be2c0db9 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; 45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
46 softmac->scaninfo = NULL; 46 softmac->scaninfo = NULL;
47 47
48 softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
49
48 /* TODO: initialise all the other callbacks in the ieee struct 50 /* TODO: initialise all the other callbacks in the ieee struct
49 * (once they're written) 51 * (once they're written)
50 */ 52 */
@@ -87,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
87 ieee80211softmac_wait_for_scan(sm); 89 ieee80211softmac_wait_for_scan(sm);
88 90
89 spin_lock_irqsave(&sm->lock, flags); 91 spin_lock_irqsave(&sm->lock, flags);
92 sm->running = 0;
93
90 /* Free all pending assoc work items */ 94 /* Free all pending assoc work items */
91 cancel_delayed_work(&sm->associnfo.work); 95 cancel_delayed_work(&sm->associnfo.work);
92 96
@@ -202,6 +206,8 @@ void ieee80211softmac_start(struct net_device *dev)
202 assert(0); 206 assert(0);
203 if (mac->txrates_change) 207 if (mac->txrates_change)
204 mac->txrates_change(dev, change, &oldrates); 208 mac->txrates_change(dev, change, &oldrates);
209
210 mac->running = 1;
205} 211}
206EXPORT_SYMBOL_GPL(ieee80211softmac_start); 212EXPORT_SYMBOL_GPL(ieee80211softmac_start);
207 213
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b45d09..d31cf77498c4 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
47 sm->scanning = 1; 47 sm->scanning = 1;
48 spin_unlock_irqrestore(&sm->lock, flags); 48 spin_unlock_irqrestore(&sm->lock, flags);
49 49
50 netif_tx_disable(sm->ieee->dev);
50 ret = sm->start_scan(sm->dev); 51 ret = sm->start_scan(sm->dev);
51 if (ret) { 52 if (ret) {
52 spin_lock_irqsave(&sm->lock, flags); 53 spin_lock_irqsave(&sm->lock, flags);
@@ -114,7 +115,15 @@ void ieee80211softmac_scan(void *d)
114 // TODO: is this if correct, or should we do this only if scanning from assoc request? 115 // TODO: is this if correct, or should we do this only if scanning from assoc request?
115 if (sm->associnfo.req_essid.len) 116 if (sm->associnfo.req_essid.len)
116 ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); 117 ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
118
119 spin_lock_irqsave(&sm->lock, flags);
120 if (unlikely(!sm->running)) {
121 /* Prevent reschedule on workqueue flush */
122 spin_unlock_irqrestore(&sm->lock, flags);
123 break;
124 }
117 schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); 125 schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
126 spin_unlock_irqrestore(&sm->lock, flags);
118 return; 127 return;
119 } else { 128 } else {
120 dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); 129 dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
@@ -239,6 +248,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
239 if (net) 248 if (net)
240 sm->set_channel(sm->dev, net->channel); 249 sm->set_channel(sm->dev, net->channel);
241 } 250 }
251 netif_wake_queue(sm->ieee->dev);
242 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); 252 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
243} 253}
244EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); 254EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index b559aa9b5507..27edb2b5581a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -27,7 +27,8 @@
27#include "ieee80211softmac_priv.h" 27#include "ieee80211softmac_priv.h"
28 28
29#include <net/iw_handler.h> 29#include <net/iw_handler.h>
30 30/* for is_broadcast_ether_addr and is_zero_ether_addr */
31#include <linux/etherdevice.h>
31 32
32int 33int
33ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, 34ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
@@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
41EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); 42EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
42 43
43 44
45/* if we're still scanning, return -EAGAIN so that userspace tools
46 * can get the complete scan results, otherwise return 0. */
44int 47int
45ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, 48ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
46 struct iw_request_info *info, 49 struct iw_request_info *info,
47 union iwreq_data *data, 50 union iwreq_data *data,
48 char *extra) 51 char *extra)
49{ 52{
53 unsigned long flags;
50 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); 54 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
55
56 spin_lock_irqsave(&sm->lock, flags);
57 if (sm->scanning) {
58 spin_unlock_irqrestore(&sm->lock, flags);
59 return -EAGAIN;
60 }
61 spin_unlock_irqrestore(&sm->lock, flags);
51 return ieee80211_wx_get_scan(sm->ieee, info, data, extra); 62 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
52} 63}
53EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); 64EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
@@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
73 sm->associnfo.static_essid = 1; 84 sm->associnfo.static_essid = 1;
74 } 85 }
75 } 86 }
76 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
77 87
78 /* set our requested ESSID length. 88 /* set our requested ESSID length.
79 * If applicable, we have already copied the data in */ 89 * If applicable, we have already copied the data in */
@@ -300,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
300 char *extra) 310 char *extra)
301{ 311{
302 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); 312 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
303 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
304 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
305 unsigned long flags; 313 unsigned long flags;
306 314
307 /* sanity check */ 315 /* sanity check */
@@ -310,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
310 } 318 }
311 319
312 spin_lock_irqsave(&mac->lock, flags); 320 spin_lock_irqsave(&mac->lock, flags);
313 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || 321 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
314 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { 322 /* the bssid we have is not to be fixed any longer,
315 schedule_work(&mac->associnfo.work); 323 * and we should reassociate to the best AP. */
316 goto out; 324 mac->associnfo.bssfixed = 0;
325 /* force reassociation */
326 mac->associnfo.bssvalid = 0;
327 if (mac->associated)
328 schedule_work(&mac->associnfo.work);
329 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
330 /* the bssid we have is no longer fixed */
331 mac->associnfo.bssfixed = 0;
317 } else { 332 } else {
318 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { 333 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
319 if (mac->associnfo.associating || mac->associated) { 334 if (mac->associnfo.associating || mac->associated) {
@@ -323,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
323 } else { 338 } else {
324 /* copy new value in data->ap_addr.sa_data to bssid */ 339 /* copy new value in data->ap_addr.sa_data to bssid */
325 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); 340 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
326 } 341 }
342 /* tell the other code that this bssid should be used no matter what */
343 mac->associnfo.bssfixed = 1;
327 /* queue associate if new bssid or (old one again and not associated) */ 344 /* queue associate if new bssid or (old one again and not associated) */
328 schedule_work(&mac->associnfo.work); 345 schedule_work(&mac->associnfo.work);
329 } 346 }
330 347
331out: 348 out:
332 spin_unlock_irqrestore(&mac->lock, flags); 349 spin_unlock_irqrestore(&mac->lock, flags);
333 return 0; 350 return 0;
334} 351}