diff options
Diffstat (limited to 'net/ieee80211/softmac')
-rw-r--r-- | net/ieee80211/softmac/Kconfig | 1 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 42 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_auth.c | 16 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_event.c | 40 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_io.c | 18 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_module.c | 6 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_scan.c | 10 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_wx.c | 37 |
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 @@ | |||
1 | config IEEE80211_SOFTMAC | 1 | config 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 | ||
61 | void | 62 | void |
@@ -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 | |||
128 | ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) | 129 | ieee80211softmac_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 | } |
206 | EXPORT_SYMBOL_GPL(ieee80211softmac_start); | 212 | EXPORT_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 | } |
244 | EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); | 254 | EXPORT_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 | ||
32 | int | 33 | int |
33 | ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, | 34 | ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, |
@@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, | |||
41 | EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); | 42 | EXPORT_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. */ | ||
44 | int | 47 | int |
45 | ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, | 48 | ieee80211softmac_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 | } |
53 | EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); | 64 | EXPORT_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 | ||
331 | out: | 348 | out: |
332 | spin_unlock_irqrestore(&mac->lock, flags); | 349 | spin_unlock_irqrestore(&mac->lock, flags); |
333 | return 0; | 350 | return 0; |
334 | } | 351 | } |