[PATCH] bcm43xx: fix race condition in periodic work handler
[deliverable/linux.git] / net / ieee80211 / softmac / ieee80211softmac_module.c
CommitLineData
4855d25b
JB
1/*
2 * Contains some basic softmac functions along with module registration code etc.
3 *
79859051
JB
4 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5 * Joseph Jezak <josejx@gentoo.org>
6 * Larry Finger <Larry.Finger@lwfinger.net>
7 * Danny van Dyk <kugelfang@gentoo.org>
8 * Michael Buesch <mbuesch@freenet.de>
4855d25b
JB
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * The full GNU General Public License is included in this distribution in the
24 * file called COPYING.
25 */
26
370121e5
JB
27#include "ieee80211softmac_priv.h"
28#include <linux/sort.h>
8462fe3c 29#include <linux/etherdevice.h>
370121e5
JB
30
31struct net_device *alloc_ieee80211softmac(int sizeof_priv)
32{
33 struct ieee80211softmac_device *softmac;
34 struct net_device *dev;
35
36 dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv);
37 softmac = ieee80211_priv(dev);
38 softmac->dev = dev;
39 softmac->ieee = netdev_priv(dev);
40 spin_lock_init(&softmac->lock);
41
42 softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
43 softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
44 softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
b6c7658e 45 softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
370121e5 46 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
5acd0c41 47 softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
370121e5
JB
48 softmac->scaninfo = NULL;
49
818667f7
JB
50 softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
51
370121e5
JB
52 /* TODO: initialise all the other callbacks in the ieee struct
53 * (once they're written)
54 */
55
370121e5
JB
56 INIT_LIST_HEAD(&softmac->auth_queue);
57 INIT_LIST_HEAD(&softmac->network_list);
58 INIT_LIST_HEAD(&softmac->events);
59
60 INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac);
61 INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac);
62 softmac->start_scan = ieee80211softmac_start_scan_implementation;
63 softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
64 softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
65
2dd50801
JB
66 /* to start with, we can't send anything ... */
67 netif_carrier_off(dev);
370121e5 68
370121e5 69 return dev;
370121e5 70}
4c718cfd 71EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
370121e5
JB
72
73/* Clears the pending work queue items, stops all scans, etc. */
74void
75ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
76{
77 unsigned long flags;
78 struct ieee80211softmac_event *eventptr, *eventtmp;
79 struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
80 struct ieee80211softmac_network *netptr, *nettmp;
81
82 ieee80211softmac_stop_scan(sm);
83 ieee80211softmac_wait_for_scan(sm);
84
85 spin_lock_irqsave(&sm->lock, flags);
d57336e3
DD
86 sm->running = 0;
87
370121e5
JB
88 /* Free all pending assoc work items */
89 cancel_delayed_work(&sm->associnfo.work);
90
91 /* Free all pending scan work items */
92 if(sm->scaninfo != NULL)
93 cancel_delayed_work(&sm->scaninfo->softmac_scan);
94
95 /* Free all pending auth work items */
96 list_for_each_entry(authptr, &sm->auth_queue, list)
97 cancel_delayed_work(&authptr->work);
98
99 /* delete all pending event calls and work items */
100 list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
101 cancel_delayed_work(&eventptr->work);
102
103 spin_unlock_irqrestore(&sm->lock, flags);
5c4df6da 104 flush_scheduled_work();
370121e5 105
b2b9b651 106 /* now we should be save and no longer need locking... */
370121e5
JB
107 spin_lock_irqsave(&sm->lock, flags);
108 /* Free all pending auth work items */
109 list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) {
110 list_del(&authptr->list);
111 kfree(authptr);
112 }
113
114 /* delete all pending event calls and work items */
115 list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
116 list_del(&eventptr->list);
117 kfree(eventptr);
118 }
119
120 /* Free all networks */
121 list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
122 ieee80211softmac_del_network_locked(sm, netptr);
123 if(netptr->challenge != NULL)
124 kfree(netptr->challenge);
125 kfree(netptr);
126 }
127
128 spin_unlock_irqrestore(&sm->lock, flags);
129}
4c718cfd 130EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work);
370121e5
JB
131
132void free_ieee80211softmac(struct net_device *dev)
133{
134 struct ieee80211softmac_device *sm = ieee80211_priv(dev);
135 ieee80211softmac_clear_pending_work(sm);
370121e5
JB
136 kfree(sm->scaninfo);
137 kfree(sm->wpa.IE);
138 free_ieee80211(dev);
139}
4c718cfd 140EXPORT_SYMBOL_GPL(free_ieee80211softmac);
370121e5
JB
141
142static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac)
143{
144 struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
145 /* I took out the sorting check, we're seperating by modulation now. */
146 if (ri->count)
147 return;
148 /* otherwise assume we hav'em all! */
149 if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) {
150 ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB;
151 ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB;
152 ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB;
153 ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB;
154 }
155 if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) {
156 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB;
157 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB;
158 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB;
159 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB;
160 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB;
161 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB;
162 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB;
163 ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB;
164 }
165}
166
8462fe3c
DD
167int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
168{
169 int search;
170 u8 search_rate;
171
172 for (search = 0; search < ri->count; search++) {
173 search_rate = ri->rates[search];
174 search_rate &= ~IEEE80211_BASIC_RATE_MASK;
175 if (rate == search_rate)
176 return 1;
177 }
178
179 return 0;
180}
181
d7712ac2 182u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
8462fe3c
DD
183 struct ieee80211softmac_ratesinfo *ri, int basic_only)
184{
185 u8 user_rate = mac->txrates.user_rate;
186 int i;
187
d7712ac2 188 if (ri->count == 0)
8462fe3c 189 return IEEE80211_CCK_RATE_1MB;
8462fe3c
DD
190
191 for (i = ri->count - 1; i >= 0; i--) {
192 u8 rate = ri->rates[i];
193 if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
194 continue;
195 rate &= ~IEEE80211_BASIC_RATE_MASK;
196 if (rate > user_rate)
197 continue;
198 if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
199 return rate;
200 }
201
202 /* If we haven't found a suitable rate by now, just trust the user */
203 return user_rate;
204}
d7712ac2 205EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
8462fe3c 206
5acd0c41
DD
207void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
208 u8 erp_value)
209{
210 int use_protection;
211 int short_preamble;
212 u32 changes = 0;
213
214 /* Barker preamble mode */
215 short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
216 && mac->associnfo.short_preamble_available) ? 1 : 0;
217
218 /* Protection needed? */
219 use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
220
221 if (mac->bssinfo.short_preamble != short_preamble) {
222 changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
223 mac->bssinfo.short_preamble = short_preamble;
224 }
225
226 if (mac->bssinfo.use_protection != use_protection) {
227 changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
228 mac->bssinfo.use_protection = use_protection;
229 }
230
231 if (mac->bssinfo_change && changes)
232 mac->bssinfo_change(mac->dev, changes);
233}
234
8462fe3c
DD
235void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
236{
237 struct ieee80211softmac_txrates *txrates = &mac->txrates;
8462fe3c
DD
238 u32 change = 0;
239
8462fe3c 240 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
d7712ac2 241 txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
8462fe3c
DD
242
243 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
244 txrates->default_fallback = lower_rate(mac, txrates->default_rate);
245
246 change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
d7712ac2 247 txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
8462fe3c
DD
248
249 if (mac->txrates_change)
5acd0c41 250 mac->txrates_change(mac->dev, change);
8462fe3c
DD
251
252}
253
5acd0c41 254void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
370121e5 255{
370121e5
JB
256 struct ieee80211_device *ieee = mac->ieee;
257 u32 change = 0;
8462fe3c 258 struct ieee80211softmac_txrates *txrates = &mac->txrates;
5acd0c41 259 struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
370121e5 260
370121e5
JB
261 /* TODO: We need some kind of state machine to lower the default rates
262 * if we loose too many packets.
263 */
264 /* Change the default txrate to the highest possible value.
265 * The txrate machine will lower it, if it is too high.
266 */
2638fed7
DW
267 /* FIXME: We don't correctly handle backing down to lower
268 rates, so 801.11g devices start off at 11M for now. People
269 can manually change it if they really need to, but 11M is
270 more reliable. Note similar logic in
271 ieee80211softmac_wx_set_rate() */
272 if (ieee->modulation & IEEE80211_CCK_MODULATION) {
8462fe3c 273 txrates->user_rate = IEEE80211_CCK_RATE_11MB;
2638fed7 274 } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
8462fe3c 275 txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
370121e5
JB
276 } else
277 assert(0);
8462fe3c
DD
278
279 txrates->default_rate = IEEE80211_CCK_RATE_1MB;
280 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
281
282 txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
283 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
284
285 txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
286 change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
287
288 txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
289 change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
290
370121e5 291 if (mac->txrates_change)
5acd0c41
DD
292 mac->txrates_change(mac->dev, change);
293
294 change = 0;
295
296 bssinfo->supported_rates.count = 0;
297 memset(bssinfo->supported_rates.rates, 0,
298 sizeof(bssinfo->supported_rates.rates));
299 change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
300
301 bssinfo->short_preamble = 0;
302 change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
303
304 bssinfo->use_protection = 0;
305 change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
306
307 if (mac->bssinfo_change)
308 mac->bssinfo_change(mac->dev, change);
d57336e3
DD
309
310 mac->running = 1;
370121e5 311}
8462fe3c
DD
312
313void ieee80211softmac_start(struct net_device *dev)
314{
315 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
316
317 ieee80211softmac_start_check_rates(mac);
5acd0c41 318 ieee80211softmac_init_bss(mac);
8462fe3c 319}
4c718cfd 320EXPORT_SYMBOL_GPL(ieee80211softmac_start);
370121e5
JB
321
322void ieee80211softmac_stop(struct net_device *dev)
323{
324 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
325
326 ieee80211softmac_clear_pending_work(mac);
327}
4c718cfd 328EXPORT_SYMBOL_GPL(ieee80211softmac_stop);
370121e5
JB
329
330void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates)
331{
332 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
333 unsigned long flags;
334
335 spin_lock_irqsave(&mac->lock, flags);
336 memcpy(mac->ratesinfo.rates, rates, count);
337 mac->ratesinfo.count = count;
338 spin_unlock_irqrestore(&mac->lock, flags);
339}
4c718cfd 340EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates);
370121e5
JB
341
342static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate)
343{
344 int i;
345 struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
346
347 for (i=0; i<ri->count-1; i++) {
348 if (ri->rates[i] == rate)
349 return ri->rates[i+1];
350 }
351 /* I guess we can't go any higher... */
352 return ri->rates[ri->count];
353}
354
355u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta)
356{
357 int i;
358 struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
359
360 for (i=delta; i<ri->count; i++) {
361 if (ri->rates[i] == rate)
362 return ri->rates[i-delta];
363 }
364 /* I guess we can't go any lower... */
365 return ri->rates[0];
366}
367
368static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
369 int amount)
370{
370121e5
JB
371 u8 default_rate = mac->txrates.default_rate;
372 u8 default_fallback = mac->txrates.default_fallback;
373 u32 changes = 0;
374
375 //TODO: This is highly experimental code.
376 // Maybe the dynamic rate selection does not work
377 // and it has to be removed again.
378
379printk("badness %d\n", mac->txrate_badness);
380 mac->txrate_badness += amount;
381 if (mac->txrate_badness <= -1000) {
382 /* Very small badness. Try a faster bitrate. */
370121e5
JB
383 default_rate = raise_rate(mac, default_rate);
384 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
385 default_fallback = get_fallback_rate(mac, default_rate);
386 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
387 mac->txrate_badness = 0;
388printk("Bitrate raised to %u\n", default_rate);
389 } else if (mac->txrate_badness >= 10000) {
390 /* Very high badness. Try a slower bitrate. */
370121e5
JB
391 default_rate = lower_rate(mac, default_rate);
392 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
393 default_fallback = get_fallback_rate(mac, default_rate);
394 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
395 mac->txrate_badness = 0;
396printk("Bitrate lowered to %u\n", default_rate);
397 }
398
399 mac->txrates.default_rate = default_rate;
400 mac->txrates.default_fallback = default_fallback;
401
402 if (changes && mac->txrates_change)
5acd0c41 403 mac->txrates_change(mac->dev, changes);
370121e5
JB
404}
405
406void ieee80211softmac_fragment_lost(struct net_device *dev,
407 u16 wl_seq)
408{
409 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
410 unsigned long flags;
411
412 spin_lock_irqsave(&mac->lock, flags);
413 ieee80211softmac_add_txrates_badness(mac, 1000);
414 //TODO
415
416 spin_unlock_irqrestore(&mac->lock, flags);
417}
4c718cfd 418EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost);
370121e5
JB
419
420static int rate_cmp(const void *a_, const void *b_) {
421 u8 *a, *b;
422 a = (u8*)a_;
423 b = (u8*)b_;
424 return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK));
425}
426
427/* Allocate a softmac network struct and fill it from a network */
428struct ieee80211softmac_network *
429ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
430 struct ieee80211_network *net)
431{
432 struct ieee80211softmac_network *softnet;
433 softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC);
434 if(softnet == NULL)
435 return NULL;
436 memcpy(softnet->bssid, net->bssid, ETH_ALEN);
437 softnet->channel = net->channel;
438 softnet->essid.len = net->ssid_len;
439 memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
440
441 /* copy rates over */
442 softnet->supported_rates.count = net->rates_len;
443 memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
444 memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
445 softnet->supported_rates.count += net->rates_ex_len;
446 sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
5acd0c41
DD
447
448 /* we save the ERP value because it is needed at association time, and
449 * many AP's do not include an ERP IE in the association response. */
450 softnet->erp_value = net->erp_value;
451
370121e5
JB
452 softnet->capabilities = net->capability;
453 return softnet;
454}
455
456
457/* Add a network to the list, while locked */
458void
459ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
460 struct ieee80211softmac_network *add_net)
461{
462 struct list_head *list_ptr;
463 struct ieee80211softmac_network *softmac_net = NULL;
464
465 list_for_each(list_ptr, &mac->network_list) {
466 softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
467 if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
468 break;
469 else
470 softmac_net = NULL;
471 }
472 if(softmac_net == NULL)
473 list_add(&(add_net->list), &mac->network_list);
474}
475
476/* Add a network to the list, with locking */
477void
478ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
479 struct ieee80211softmac_network *add_net)
480{
481 unsigned long flags;
482 spin_lock_irqsave(&mac->lock, flags);
483 ieee80211softmac_add_network_locked(mac, add_net);
484 spin_unlock_irqrestore(&mac->lock, flags);
485}
486
487
488/* Delete a network from the list, while locked*/
489void
490ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
491 struct ieee80211softmac_network *del_net)
492{
493 list_del(&(del_net->list));
494}
495
496/* Delete a network from the list with locking */
497void
498ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
499 struct ieee80211softmac_network *del_net)
500{
501 unsigned long flags;
502 spin_lock_irqsave(&mac->lock, flags);
503 ieee80211softmac_del_network_locked(mac, del_net);
504 spin_unlock_irqrestore(&mac->lock, flags);
505}
506
507/* Get a network from the list by MAC while locked */
508struct ieee80211softmac_network *
509ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
510 u8 *bssid)
511{
512 struct list_head *list_ptr;
513 struct ieee80211softmac_network *softmac_net = NULL;
514 list_for_each(list_ptr, &mac->network_list) {
515 softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
516 if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
517 break;
518 else
519 softmac_net = NULL;
520 }
521 return softmac_net;
522}
523
524/* Get a network from the list by BSSID with locking */
525struct ieee80211softmac_network *
526ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac,
527 u8 *bssid)
528{
529 unsigned long flags;
530 struct ieee80211softmac_network *softmac_net;
531
532 spin_lock_irqsave(&mac->lock, flags);
533 softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
534 spin_unlock_irqrestore(&mac->lock, flags);
535 return softmac_net;
536}
537
538/* Get a network from the list by ESSID while locked */
539struct ieee80211softmac_network *
540ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
541 struct ieee80211softmac_essid *essid)
542{
543 struct list_head *list_ptr;
544 struct ieee80211softmac_network *softmac_net = NULL;
545
546 list_for_each(list_ptr, &mac->network_list) {
547 softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
548 if (softmac_net->essid.len == essid->len &&
549 !memcmp(softmac_net->essid.data, essid->data, essid->len))
550 return softmac_net;
551 }
552 return NULL;
553}
554
555/* Get a network from the list by ESSID with locking */
556struct ieee80211softmac_network *
557ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
558 struct ieee80211softmac_essid *essid)
559{
560 unsigned long flags;
561 struct ieee80211softmac_network *softmac_net = NULL;
562
563 spin_lock_irqsave(&mac->lock, flags);
564 softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
565 spin_unlock_irqrestore(&mac->lock, flags);
566 return softmac_net;
567}
568
569MODULE_LICENSE("GPL");
9ebdd466
JB
570MODULE_AUTHOR("Johannes Berg");
571MODULE_AUTHOR("Joseph Jezak");
572MODULE_AUTHOR("Larry Finger");
573MODULE_AUTHOR("Danny van Dyk");
574MODULE_AUTHOR("Michael Buesch");
575MODULE_DESCRIPTION("802.11 software MAC");
This page took 0.096394 seconds and 5 git commands to generate.