Merge tag 'hix5hd2-dt-for-3.18' of git://github.com/hisilicon/linux-hisi into next/dt
[deliverable/linux.git] / net / wireless / core.c
CommitLineData
704232c2
JB
1/*
2 * This is the linux wireless configuration interface.
3 *
5f2aa25e 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
704232c2
JB
5 */
6
e9c0268f
JP
7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
704232c2
JB
9#include <linux/if.h>
10#include <linux/module.h>
11#include <linux/err.h>
704232c2 12#include <linux/list.h>
5a0e3ad6 13#include <linux/slab.h>
704232c2
JB
14#include <linux/nl80211.h>
15#include <linux/debugfs.h>
16#include <linux/notifier.h>
17#include <linux/device.h>
16a832e7 18#include <linux/etherdevice.h>
1f87f7d3 19#include <linux/rtnetlink.h>
d43c36dc 20#include <linux/sched.h>
704232c2
JB
21#include <net/genetlink.h>
22#include <net/cfg80211.h>
55682965 23#include "nl80211.h"
704232c2
JB
24#include "core.h"
25#include "sysfs.h"
1ac61302 26#include "debugfs.h"
a9a11622 27#include "wext-compat.h"
e35e4d28 28#include "rdev-ops.h"
704232c2
JB
29
30/* name for sysfs, %d is appended */
31#define PHY_NAME "phy"
32
33MODULE_AUTHOR("Johannes Berg");
34MODULE_LICENSE("GPL");
35MODULE_DESCRIPTION("wireless configuration support");
fb4e1568 36MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
704232c2 37
5fe231e8 38/* RCU-protected (and RTNL for writers) */
79c97e97 39LIST_HEAD(cfg80211_rdev_list);
f5ea9120 40int cfg80211_rdev_list_generation;
a1794390 41
704232c2
JB
42/* for debugfs */
43static struct dentry *ieee80211_debugfs_dir;
44
e60d7443
AB
45/* for the cleanup, scan and event works */
46struct workqueue_struct *cfg80211_wq;
47
40db6c77
AK
48static bool cfg80211_disable_40mhz_24ghz;
49module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
50MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
51 "Disable 40MHz support in the 2.4GHz band");
52
79c97e97 53struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
55682965 54{
79c97e97 55 struct cfg80211_registered_device *result = NULL, *rdev;
55682965 56
5fe231e8 57 ASSERT_RTNL();
761cf7ec 58
79c97e97
JB
59 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
60 if (rdev->wiphy_idx == wiphy_idx) {
61 result = rdev;
55682965
JB
62 break;
63 }
64 }
65
66 return result;
67}
68
806a9e39
LR
69int get_wiphy_idx(struct wiphy *wiphy)
70{
f26cbf40 71 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
f4173766 72
79c97e97 73 return rdev->wiphy_idx;
806a9e39
LR
74}
75
806a9e39
LR
76struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
77{
79c97e97 78 struct cfg80211_registered_device *rdev;
806a9e39 79
5fe231e8 80 ASSERT_RTNL();
806a9e39 81
79c97e97
JB
82 rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
83 if (!rdev)
806a9e39 84 return NULL;
79c97e97 85 return &rdev->wiphy;
806a9e39
LR
86}
87
55682965
JB
88int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
89 char *newname)
90{
79c97e97 91 struct cfg80211_registered_device *rdev2;
7623225f 92 int wiphy_idx, taken = -1, result, digits;
55682965 93
5fe231e8 94 ASSERT_RTNL();
2940bb69 95
7623225f
JB
96 /* prohibit calling the thing phy%d when %d is not its number */
97 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
98 if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
99 /* count number of places needed to print wiphy_idx */
100 digits = 1;
101 while (wiphy_idx /= 10)
102 digits++;
103 /*
104 * deny the name if it is phy<idx> where <idx> is printed
105 * without leading zeroes. taken == strlen(newname) here
106 */
107 if (taken == strlen(PHY_NAME) + digits)
108 return -EINVAL;
109 }
110
111
2940bb69 112 /* Ignore nop renames */
2940bb69 113 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
4bbf4d56 114 return 0;
2940bb69
EB
115
116 /* Ensure another device does not already have this name. */
79c97e97
JB
117 list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
118 if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
7623225f 119 return -EINVAL;
55682965 120
55682965
JB
121 result = device_rename(&rdev->wiphy.dev, newname);
122 if (result)
4bbf4d56 123 return result;
55682965 124
33c0360b
JB
125 if (rdev->wiphy.debugfsdir &&
126 !debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
55682965
JB
127 rdev->wiphy.debugfsdir,
128 rdev->wiphy.debugfsdir->d_parent,
129 newname))
e9c0268f 130 pr_err("failed to rename debugfs dir to %s!\n", newname);
55682965 131
3bb20556 132 nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
55682965 133
4bbf4d56 134 return 0;
55682965
JB
135}
136
463d0183
JB
137int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
138 struct net *net)
139{
140 struct wireless_dev *wdev;
141 int err = 0;
142
5be83de5 143 if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
463d0183
JB
144 return -EOPNOTSUPP;
145
89a54e48 146 list_for_each_entry(wdev, &rdev->wdev_list, list) {
ba22fb5b
JB
147 if (!wdev->netdev)
148 continue;
463d0183
JB
149 wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
150 err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
151 if (err)
152 break;
153 wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
154 }
155
156 if (err) {
157 /* failed -- clean up to old netns */
158 net = wiphy_net(&rdev->wiphy);
159
89a54e48 160 list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list,
463d0183 161 list) {
ba22fb5b
JB
162 if (!wdev->netdev)
163 continue;
463d0183
JB
164 wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
165 err = dev_change_net_namespace(wdev->netdev, net,
166 "wlan%d");
167 WARN_ON(err);
168 wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
169 }
04600794
JB
170
171 return err;
463d0183
JB
172 }
173
174 wiphy_net_set(&rdev->wiphy, net);
175
04600794
JB
176 err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev));
177 WARN_ON(err);
178
179 return 0;
463d0183
JB
180}
181
1f87f7d3
JB
182static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
183{
79c97e97 184 struct cfg80211_registered_device *rdev = data;
1f87f7d3 185
e35e4d28 186 rdev_rfkill_poll(rdev);
1f87f7d3
JB
187}
188
f9f47529
JB
189void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
190 struct wireless_dev *wdev)
191{
5fe231e8 192 ASSERT_RTNL();
f9f47529
JB
193
194 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
195 return;
196
197 if (!wdev->p2p_started)
198 return;
199
200 rdev_stop_p2p_device(rdev, wdev);
201 wdev->p2p_started = false;
202
203 rdev->opencount--;
204
a617302c
JB
205 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
206 if (WARN_ON(!rdev->scan_req->notified))
207 rdev->scan_req->aborted = true;
f9d15d16 208 ___cfg80211_scan_done(rdev, false);
a617302c 209 }
f9f47529
JB
210}
211
f6837ba8 212void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
1f87f7d3 213{
f6837ba8 214 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3
JB
215 struct wireless_dev *wdev;
216
f6837ba8 217 ASSERT_RTNL();
f9f47529 218
98104fde
JB
219 list_for_each_entry(wdev, &rdev->wdev_list, list) {
220 if (wdev->netdev) {
ba22fb5b 221 dev_close(wdev->netdev);
98104fde
JB
222 continue;
223 }
224 /* otherwise, check iftype */
225 switch (wdev->iftype) {
226 case NL80211_IFTYPE_P2P_DEVICE:
f9f47529 227 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
228 break;
229 default:
230 break;
231 }
232 }
f6837ba8
JB
233}
234EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
1f87f7d3 235
f6837ba8
JB
236static int cfg80211_rfkill_set_block(void *data, bool blocked)
237{
238 struct cfg80211_registered_device *rdev = data;
239
240 if (!blocked)
241 return 0;
242
243 rtnl_lock();
244 cfg80211_shutdown_all_interfaces(&rdev->wiphy);
1f87f7d3
JB
245 rtnl_unlock();
246
247 return 0;
248}
249
250static void cfg80211_rfkill_sync_work(struct work_struct *work)
251{
79c97e97 252 struct cfg80211_registered_device *rdev;
1f87f7d3 253
79c97e97
JB
254 rdev = container_of(work, struct cfg80211_registered_device, rfkill_sync);
255 cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill));
1f87f7d3
JB
256}
257
667503dd
JB
258static void cfg80211_event_work(struct work_struct *work)
259{
260 struct cfg80211_registered_device *rdev;
667503dd
JB
261
262 rdev = container_of(work, struct cfg80211_registered_device,
263 event_work);
264
265 rtnl_lock();
3d54d255 266 cfg80211_process_rdev_events(rdev);
667503dd
JB
267 rtnl_unlock();
268}
269
78f22b6a
JB
270void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
271{
272 struct cfg80211_iface_destroy *item;
273
274 ASSERT_RTNL();
275
276 spin_lock_irq(&rdev->destroy_list_lock);
277 while ((item = list_first_entry_or_null(&rdev->destroy_list,
278 struct cfg80211_iface_destroy,
279 list))) {
280 struct wireless_dev *wdev, *tmp;
281 u32 nlportid = item->nlportid;
282
283 list_del(&item->list);
284 kfree(item);
285 spin_unlock_irq(&rdev->destroy_list_lock);
286
287 list_for_each_entry_safe(wdev, tmp, &rdev->wdev_list, list) {
288 if (nlportid == wdev->owner_nlportid)
289 rdev_del_virtual_intf(rdev, wdev);
290 }
291
292 spin_lock_irq(&rdev->destroy_list_lock);
293 }
294 spin_unlock_irq(&rdev->destroy_list_lock);
295}
296
297static void cfg80211_destroy_iface_wk(struct work_struct *work)
298{
299 struct cfg80211_registered_device *rdev;
300
301 rdev = container_of(work, struct cfg80211_registered_device,
302 destroy_work);
303
304 rtnl_lock();
305 cfg80211_destroy_ifaces(rdev);
306 rtnl_unlock();
307}
308
704232c2
JB
309/* exported functions */
310
3dcf670b 311struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
704232c2 312{
73810b77 313 static atomic_t wiphy_counter = ATOMIC_INIT(0);
7623225f
JB
314
315 struct cfg80211_registered_device *rdev;
704232c2
JB
316 int alloc_size;
317
0b20633d
JB
318 WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
319 WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
320 WARN_ON(ops->connect && !ops->disconnect);
321 WARN_ON(ops->join_ibss && !ops->leave_ibss);
322 WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
323 WARN_ON(ops->add_station && !ops->del_station);
324 WARN_ON(ops->add_mpath && !ops->del_mpath);
29cbe68c 325 WARN_ON(ops->join_mesh && !ops->leave_mesh);
41ade00f 326
79c97e97 327 alloc_size = sizeof(*rdev) + sizeof_priv;
704232c2 328
79c97e97
JB
329 rdev = kzalloc(alloc_size, GFP_KERNEL);
330 if (!rdev)
704232c2
JB
331 return NULL;
332
79c97e97 333 rdev->ops = ops;
704232c2 334
73810b77 335 rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
a4d73ee1 336
f4173766 337 if (unlikely(rdev->wiphy_idx < 0)) {
7623225f 338 /* ugh, wrapped! */
73810b77 339 atomic_dec(&wiphy_counter);
79c97e97 340 kfree(rdev);
704232c2
JB
341 return NULL;
342 }
704232c2 343
9b881963
JB
344 /* atomic_inc_return makes it start at 1, make it start at 0 */
345 rdev->wiphy_idx--;
346
7623225f
JB
347 /* give it a proper name */
348 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
349
89a54e48 350 INIT_LIST_HEAD(&rdev->wdev_list);
37c73b5f
BG
351 INIT_LIST_HEAD(&rdev->beacon_registrations);
352 spin_lock_init(&rdev->beacon_registrations_lock);
79c97e97
JB
353 spin_lock_init(&rdev->bss_lock);
354 INIT_LIST_HEAD(&rdev->bss_list);
355 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
807f8a8c 356 INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results);
04f39047
SW
357 INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
358 cfg80211_dfs_channels_update_work);
3d23e349
JB
359#ifdef CONFIG_CFG80211_WEXT
360 rdev->wiphy.wext = &cfg80211_wext_handler;
361#endif
362
79c97e97
JB
363 device_initialize(&rdev->wiphy.dev);
364 rdev->wiphy.dev.class = &ieee80211_class;
365 rdev->wiphy.dev.platform_data = rdev;
366
78f22b6a
JB
367 INIT_LIST_HEAD(&rdev->destroy_list);
368 spin_lock_init(&rdev->destroy_list_lock);
369 INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
370
5be83de5
JB
371#ifdef CONFIG_CFG80211_DEFAULT_PS
372 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
373#endif
16cb9d42 374
463d0183
JB
375 wiphy_net_set(&rdev->wiphy, &init_net);
376
79c97e97
JB
377 rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
378 rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev),
379 &rdev->wiphy.dev, RFKILL_TYPE_WLAN,
380 &rdev->rfkill_ops, rdev);
381
382 if (!rdev->rfkill) {
383 kfree(rdev);
1f87f7d3
JB
384 return NULL;
385 }
386
79c97e97
JB
387 INIT_WORK(&rdev->rfkill_sync, cfg80211_rfkill_sync_work);
388 INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
389 INIT_WORK(&rdev->event_work, cfg80211_event_work);
1f87f7d3 390
ad002395
JB
391 init_waitqueue_head(&rdev->dev_wait);
392
b9a5f8ca
JM
393 /*
394 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
395 * Fragmentation and RTS threshold are disabled by default with the
396 * special -1 value.
397 */
79c97e97
JB
398 rdev->wiphy.retry_short = 7;
399 rdev->wiphy.retry_long = 4;
400 rdev->wiphy.frag_threshold = (u32) -1;
401 rdev->wiphy.rts_threshold = (u32) -1;
81077e82 402 rdev->wiphy.coverage_class = 0;
b9a5f8ca 403
9a774c78
AO
404 rdev->wiphy.max_num_csa_counters = 1;
405
79c97e97 406 return &rdev->wiphy;
704232c2
JB
407}
408EXPORT_SYMBOL(wiphy_new);
409
7527a782
JB
410static int wiphy_verify_combinations(struct wiphy *wiphy)
411{
412 const struct ieee80211_iface_combination *c;
413 int i, j;
414
7527a782
JB
415 for (i = 0; i < wiphy->n_iface_combinations; i++) {
416 u32 cnt = 0;
417 u16 all_iftypes = 0;
418
419 c = &wiphy->iface_combinations[i];
420
11c4a075
SW
421 /*
422 * Combinations with just one interface aren't real,
423 * however we make an exception for DFS.
424 */
425 if (WARN_ON((c->max_interfaces < 2) && !c->radar_detect_widths))
7527a782
JB
426 return -EINVAL;
427
428 /* Need at least one channel */
429 if (WARN_ON(!c->num_different_channels))
430 return -EINVAL;
431
d4e50c59
MK
432 /*
433 * Put a sane limit on maximum number of different
434 * channels to simplify channel accounting code.
435 */
436 if (WARN_ON(c->num_different_channels >
437 CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
438 return -EINVAL;
439
11c4a075
SW
440 /* DFS only works on one channel. */
441 if (WARN_ON(c->radar_detect_widths &&
442 (c->num_different_channels > 1)))
443 return -EINVAL;
444
7527a782
JB
445 if (WARN_ON(!c->n_limits))
446 return -EINVAL;
447
448 for (j = 0; j < c->n_limits; j++) {
449 u16 types = c->limits[j].types;
450
b6a55015 451 /* interface types shouldn't overlap */
7527a782
JB
452 if (WARN_ON(types & all_iftypes))
453 return -EINVAL;
454 all_iftypes |= types;
455
456 if (WARN_ON(!c->limits[j].max))
457 return -EINVAL;
458
459 /* Shouldn't list software iftypes in combinations! */
460 if (WARN_ON(wiphy->software_iftypes & types))
461 return -EINVAL;
462
98104fde
JB
463 /* Only a single P2P_DEVICE can be allowed */
464 if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) &&
465 c->limits[j].max > 1))
466 return -EINVAL;
467
7527a782
JB
468 cnt += c->limits[j].max;
469 /*
470 * Don't advertise an unsupported type
471 * in a combination.
472 */
473 if (WARN_ON((wiphy->interface_modes & types) != types))
474 return -EINVAL;
475 }
476
477 /* You can't even choose that many! */
478 if (WARN_ON(cnt < c->max_interfaces))
479 return -EINVAL;
480 }
481
482 return 0;
483}
484
704232c2
JB
485int wiphy_register(struct wiphy *wiphy)
486{
f26cbf40 487 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
704232c2 488 int res;
8318d78a
JB
489 enum ieee80211_band band;
490 struct ieee80211_supported_band *sband;
491 bool have_band = false;
492 int i;
f59ac048
LR
493 u16 ifmodes = wiphy->interface_modes;
494
dda444d5
SW
495 /*
496 * There are major locking problems in nl80211/mac80211 for CSA,
497 * disable for all drivers until this has been reworked.
498 */
499 wiphy->flags &= ~WIPHY_FLAG_HAS_CHANNEL_SWITCH;
500
dfb89c56 501#ifdef CONFIG_PM
964dc9e2
JB
502 if (WARN_ON(wiphy->wowlan &&
503 (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
504 !(wiphy->wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
505 return -EINVAL;
506 if (WARN_ON(wiphy->wowlan &&
507 !wiphy->wowlan->flags && !wiphy->wowlan->n_patterns &&
508 !wiphy->wowlan->tcp))
77dbbb13 509 return -EINVAL;
dfb89c56 510#endif
77dbbb13 511
be29b99a
AK
512 if (WARN_ON(wiphy->coalesce &&
513 (!wiphy->coalesce->n_rules ||
514 !wiphy->coalesce->n_patterns) &&
515 (!wiphy->coalesce->pattern_min_len ||
516 wiphy->coalesce->pattern_min_len >
517 wiphy->coalesce->pattern_max_len)))
518 return -EINVAL;
519
562a7480
JB
520 if (WARN_ON(wiphy->ap_sme_capa &&
521 !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
522 return -EINVAL;
523
ef15aac6
JB
524 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
525 return -EINVAL;
526
527 if (WARN_ON(wiphy->addresses &&
528 !is_zero_ether_addr(wiphy->perm_addr) &&
529 memcmp(wiphy->perm_addr, wiphy->addresses[0].addr,
530 ETH_ALEN)))
531 return -EINVAL;
532
77765eaf
VT
533 if (WARN_ON(wiphy->max_acl_mac_addrs &&
534 (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) ||
535 !rdev->ops->set_mac_acl)))
536 return -EINVAL;
537
ef15aac6
JB
538 if (wiphy->addresses)
539 memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
540
f59ac048
LR
541 /* sanity check ifmodes */
542 WARN_ON(!ifmodes);
2e161f78 543 ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1;
f59ac048
LR
544 if (WARN_ON(ifmodes != wiphy->interface_modes))
545 wiphy->interface_modes = ifmodes;
8318d78a 546
7527a782
JB
547 res = wiphy_verify_combinations(wiphy);
548 if (res)
549 return res;
550
8318d78a
JB
551 /* sanity check supported bands/channels */
552 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
553 sband = wiphy->bands[band];
554 if (!sband)
555 continue;
556
557 sband->band = band;
3a0c52a6
VK
558 if (WARN_ON(!sband->n_channels))
559 return -EINVAL;
560 /*
561 * on 60gHz band, there are no legacy rates, so
562 * n_bitrates is 0
563 */
564 if (WARN_ON(band != IEEE80211_BAND_60GHZ &&
565 !sband->n_bitrates))
881d948c
JB
566 return -EINVAL;
567
40db6c77
AK
568 /*
569 * Since cfg80211_disable_40mhz_24ghz is global, we can
570 * modify the sband's ht data even if the driver uses a
571 * global structure for that.
572 */
573 if (cfg80211_disable_40mhz_24ghz &&
574 band == IEEE80211_BAND_2GHZ &&
575 sband->ht_cap.ht_supported) {
576 sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
577 sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
578 }
579
881d948c
JB
580 /*
581 * Since we use a u32 for rate bitmaps in
582 * ieee80211_get_response_rate, we cannot
583 * have more than 32 legacy rates.
584 */
585 if (WARN_ON(sband->n_bitrates > 32))
8318d78a 586 return -EINVAL;
8318d78a
JB
587
588 for (i = 0; i < sband->n_channels; i++) {
589 sband->channels[i].orig_flags =
590 sband->channels[i].flags;
c4a9fafc 591 sband->channels[i].orig_mag = INT_MAX;
8318d78a
JB
592 sband->channels[i].orig_mpwr =
593 sband->channels[i].max_power;
594 sband->channels[i].band = band;
595 }
596
597 have_band = true;
598 }
599
600 if (!have_band) {
601 WARN_ON(1);
602 return -EINVAL;
603 }
604
dfb89c56 605#ifdef CONFIG_PM
964dc9e2
JB
606 if (WARN_ON(rdev->wiphy.wowlan && rdev->wiphy.wowlan->n_patterns &&
607 (!rdev->wiphy.wowlan->pattern_min_len ||
608 rdev->wiphy.wowlan->pattern_min_len >
609 rdev->wiphy.wowlan->pattern_max_len)))
610 return -EINVAL;
dfb89c56 611#endif
ff1b6e69 612
8318d78a
JB
613 /* check and set up bitrates */
614 ieee80211_set_bitrate_flags(wiphy);
615
00c3a6ed
JB
616 rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH;
617
aa5f66d5 618 rtnl_lock();
79c97e97 619 res = device_add(&rdev->wiphy.dev);
c3d34d5d 620 if (res) {
aa5f66d5 621 rtnl_unlock();
c3d34d5d
JL
622 return res;
623 }
1f87f7d3 624
2f0accc1 625 /* set up regulatory info */
57b5ce07 626 wiphy_regulatory_register(wiphy);
2f0accc1 627
5f2aa25e 628 list_add_rcu(&rdev->list, &cfg80211_rdev_list);
f5ea9120 629 cfg80211_rdev_list_generation++;
704232c2
JB
630
631 /* add to debugfs */
79c97e97
JB
632 rdev->wiphy.debugfsdir =
633 debugfs_create_dir(wiphy_name(&rdev->wiphy),
704232c2 634 ieee80211_debugfs_dir);
79c97e97
JB
635 if (IS_ERR(rdev->wiphy.debugfsdir))
636 rdev->wiphy.debugfsdir = NULL;
704232c2 637
a2f73b6c 638 if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
73d54c9e
LR
639 struct regulatory_request request;
640
641 request.wiphy_idx = get_wiphy_idx(wiphy);
642 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
643 request.alpha2[0] = '9';
644 request.alpha2[1] = '9';
645
646 nl80211_send_reg_change_event(&request);
647 }
648
79c97e97 649 cfg80211_debugfs_rdev_add(rdev);
1ac61302 650
ecb44335
SG
651 rdev->wiphy.registered = true;
652 rtnl_unlock();
aa5f66d5
JB
653
654 res = rfkill_register(rdev->rfkill);
655 if (res) {
656 rfkill_destroy(rdev->rfkill);
657 rdev->rfkill = NULL;
658 wiphy_unregister(&rdev->wiphy);
659 return res;
660 }
661
3bb20556
JB
662 nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
663
2f0accc1 664 return 0;
704232c2
JB
665}
666EXPORT_SYMBOL(wiphy_register);
667
1f87f7d3
JB
668void wiphy_rfkill_start_polling(struct wiphy *wiphy)
669{
f26cbf40 670 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3 671
79c97e97 672 if (!rdev->ops->rfkill_poll)
1f87f7d3 673 return;
79c97e97
JB
674 rdev->rfkill_ops.poll = cfg80211_rfkill_poll;
675 rfkill_resume_polling(rdev->rfkill);
1f87f7d3
JB
676}
677EXPORT_SYMBOL(wiphy_rfkill_start_polling);
678
679void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
680{
f26cbf40 681 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3 682
79c97e97 683 rfkill_pause_polling(rdev->rfkill);
1f87f7d3
JB
684}
685EXPORT_SYMBOL(wiphy_rfkill_stop_polling);
686
704232c2
JB
687void wiphy_unregister(struct wiphy *wiphy)
688{
f26cbf40 689 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
704232c2 690
ad002395
JB
691 wait_event(rdev->dev_wait, ({
692 int __count;
5fe231e8 693 rtnl_lock();
ad002395 694 __count = rdev->opencount;
5fe231e8 695 rtnl_unlock();
c4f60846 696 __count == 0; }));
ad002395 697
aa5f66d5
JB
698 if (rdev->rfkill)
699 rfkill_unregister(rdev->rfkill);
256c90de 700
5fe231e8 701 rtnl_lock();
3bb20556 702 nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
5fe231e8
JB
703 rdev->wiphy.registered = false;
704
2fd05115 705 WARN_ON(!list_empty(&rdev->wdev_list));
ad002395
JB
706
707 /*
708 * First remove the hardware from everywhere, this makes
709 * it impossible to find from userspace.
710 */
7bcfaf2f 711 debugfs_remove_recursive(rdev->wiphy.debugfsdir);
5f2aa25e
JB
712 list_del_rcu(&rdev->list);
713 synchronize_rcu();
f16bfc1c 714
bfead080
LR
715 /*
716 * If this device got a regulatory hint tell core its
717 * free to listen now to a new shiny device regulatory hint
718 */
719 wiphy_regulatory_deregister(wiphy);
3f2355cb 720
f5ea9120 721 cfg80211_rdev_list_generation++;
79c97e97 722 device_del(&rdev->wiphy.dev);
704232c2 723
5fe231e8 724 rtnl_unlock();
6682588a 725
36e6fea8 726 flush_work(&rdev->scan_done_wk);
6682588a 727 cancel_work_sync(&rdev->conn_work);
6682588a 728 flush_work(&rdev->event_work);
04f39047 729 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
78f22b6a 730 flush_work(&rdev->destroy_work);
6d52563f 731
6abb9cb9
JB
732#ifdef CONFIG_PM
733 if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
e35e4d28 734 rdev_set_wakeup(rdev, false);
6abb9cb9 735#endif
6d52563f 736 cfg80211_rdev_free_wowlan(rdev);
be29b99a 737 cfg80211_rdev_free_coalesce(rdev);
704232c2
JB
738}
739EXPORT_SYMBOL(wiphy_unregister);
740
79c97e97 741void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
704232c2 742{
2a519311 743 struct cfg80211_internal_bss *scan, *tmp;
37c73b5f 744 struct cfg80211_beacon_registration *reg, *treg;
79c97e97 745 rfkill_destroy(rdev->rfkill);
37c73b5f
BG
746 list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
747 list_del(&reg->list);
748 kfree(reg);
749 }
79c97e97 750 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
5b112d3d 751 cfg80211_put_bss(&rdev->wiphy, &scan->pub);
79c97e97 752 kfree(rdev);
704232c2
JB
753}
754
755void wiphy_free(struct wiphy *wiphy)
756{
757 put_device(&wiphy->dev);
758}
759EXPORT_SYMBOL(wiphy_free);
760
1f87f7d3
JB
761void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
762{
f26cbf40 763 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3 764
79c97e97
JB
765 if (rfkill_set_hw_state(rdev->rfkill, blocked))
766 schedule_work(&rdev->rfkill_sync);
1f87f7d3
JB
767}
768EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
769
98104fde
JB
770void cfg80211_unregister_wdev(struct wireless_dev *wdev)
771{
f26cbf40 772 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
98104fde
JB
773
774 ASSERT_RTNL();
775
776 if (WARN_ON(wdev->netdev))
777 return;
778
98104fde
JB
779 list_del_rcu(&wdev->list);
780 rdev->devlist_generation++;
781
782 switch (wdev->iftype) {
783 case NL80211_IFTYPE_P2P_DEVICE:
f9f47529 784 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
785 break;
786 default:
787 WARN_ON_ONCE(1);
788 break;
789 }
98104fde
JB
790}
791EXPORT_SYMBOL(cfg80211_unregister_wdev);
792
f1e3d556 793static const struct device_type wiphy_type = {
053a93dd
MH
794 .name = "wlan",
795};
796
dbbae26a
MK
797void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
798 enum nl80211_iftype iftype, int num)
799{
c5a7e582 800 ASSERT_RTNL();
dbbae26a
MK
801
802 rdev->num_running_ifaces += num;
803 if (iftype == NL80211_IFTYPE_MONITOR)
804 rdev->num_running_monitor_ifaces += num;
dbbae26a
MK
805}
806
f04c2203
MK
807void __cfg80211_leave(struct cfg80211_registered_device *rdev,
808 struct wireless_dev *wdev)
81256969
SG
809{
810 struct net_device *dev = wdev->netdev;
811
24d584d7 812 ASSERT_RTNL();
f04c2203 813 ASSERT_WDEV_LOCK(wdev);
24d584d7 814
81256969
SG
815 switch (wdev->iftype) {
816 case NL80211_IFTYPE_ADHOC:
f04c2203 817 __cfg80211_leave_ibss(rdev, dev, true);
81256969
SG
818 break;
819 case NL80211_IFTYPE_P2P_CLIENT:
820 case NL80211_IFTYPE_STATION:
24d584d7
BB
821 if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
822 __cfg80211_stop_sched_scan(rdev, false);
81256969 823
81256969
SG
824#ifdef CONFIG_CFG80211_WEXT
825 kfree(wdev->wext.ie);
826 wdev->wext.ie = NULL;
827 wdev->wext.ie_len = 0;
828 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
829#endif
83739b03
JB
830 cfg80211_disconnect(rdev, dev,
831 WLAN_REASON_DEAUTH_LEAVING, true);
81256969
SG
832 break;
833 case NL80211_IFTYPE_MESH_POINT:
f04c2203 834 __cfg80211_leave_mesh(rdev, dev);
81256969
SG
835 break;
836 case NL80211_IFTYPE_AP:
74418ede 837 case NL80211_IFTYPE_P2P_GO:
f04c2203 838 __cfg80211_stop_ap(rdev, dev, true);
81256969
SG
839 break;
840 default:
841 break;
842 }
81256969
SG
843}
844
f04c2203
MK
845void cfg80211_leave(struct cfg80211_registered_device *rdev,
846 struct wireless_dev *wdev)
847{
848 wdev_lock(wdev);
849 __cfg80211_leave(rdev, wdev);
850 wdev_unlock(wdev);
851}
852
853void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
854 gfp_t gfp)
855{
856 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
857 struct cfg80211_event *ev;
858 unsigned long flags;
859
860 trace_cfg80211_stop_iface(wiphy, wdev);
861
862 ev = kzalloc(sizeof(*ev), gfp);
863 if (!ev)
864 return;
865
866 ev->type = EVENT_STOPPED;
867
868 spin_lock_irqsave(&wdev->event_lock, flags);
869 list_add_tail(&ev->list, &wdev->event_list);
870 spin_unlock_irqrestore(&wdev->event_lock, flags);
871 queue_work(cfg80211_wq, &rdev->event_work);
872}
873EXPORT_SYMBOL(cfg80211_stop_iface);
874
c4f60846 875static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
351638e7 876 unsigned long state, void *ptr)
704232c2 877{
351638e7 878 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2a783c13 879 struct wireless_dev *wdev = dev->ieee80211_ptr;
704232c2
JB
880 struct cfg80211_registered_device *rdev;
881
2a783c13 882 if (!wdev)
1f87f7d3 883 return NOTIFY_DONE;
704232c2 884
f26cbf40 885 rdev = wiphy_to_rdev(wdev->wiphy);
704232c2 886
2a783c13 887 WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
60719ffd 888
704232c2 889 switch (state) {
053a93dd
MH
890 case NETDEV_POST_INIT:
891 SET_NETDEV_DEVTYPE(dev, &wiphy_type);
892 break;
704232c2 893 case NETDEV_REGISTER:
0ff6ce7b
JB
894 /*
895 * NB: cannot take rdev->mtx here because this may be
896 * called within code protected by it when interfaces
897 * are added with nl80211.
898 */
667503dd
JB
899 mutex_init(&wdev->mtx);
900 INIT_LIST_HEAD(&wdev->event_list);
901 spin_lock_init(&wdev->event_lock);
2e161f78
JB
902 INIT_LIST_HEAD(&wdev->mgmt_registrations);
903 spin_lock_init(&wdev->mgmt_registrations_lock);
026331c4 904
89a54e48
JB
905 wdev->identifier = ++rdev->wdev_id;
906 list_add_rcu(&wdev->list, &rdev->wdev_list);
f5ea9120 907 rdev->devlist_generation++;
463d0183
JB
908 /* can only change netns with wiphy */
909 dev->features |= NETIF_F_NETNS_LOCAL;
910
704232c2
JB
911 if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
912 "phy80211")) {
e9c0268f 913 pr_err("failed to add phy80211 symlink to netdev!\n");
704232c2 914 }
2a783c13 915 wdev->netdev = dev;
3d23e349 916#ifdef CONFIG_CFG80211_WEXT
2a783c13
JB
917 wdev->wext.default_key = -1;
918 wdev->wext.default_mgmt_key = -1;
f2129354 919 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
ffb9eb3d
KV
920#endif
921
5be83de5 922 if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
ffb9eb3d 923 wdev->ps = true;
5be83de5 924 else
ffb9eb3d 925 wdev->ps = false;
9043f3b8
JO
926 /* allow mac80211 to determine the timeout */
927 wdev->ps_timeout = -1;
ffb9eb3d 928
ad4bb6f8 929 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
074ac8df 930 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
ad4bb6f8
JB
931 wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
932 dev->priv_flags |= IFF_DONT_BRIDGE;
704232c2 933 break;
04a773ad 934 case NETDEV_GOING_DOWN:
81256969 935 cfg80211_leave(rdev, wdev);
01a0ac41
JB
936 break;
937 case NETDEV_DOWN:
dbbae26a 938 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
a617302c
JB
939 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
940 if (WARN_ON(!rdev->scan_req->notified))
941 rdev->scan_req->aborted = true;
f9d15d16 942 ___cfg80211_scan_done(rdev, false);
a617302c 943 }
5fe231e8
JB
944
945 if (WARN_ON(rdev->sched_scan_req &&
946 rdev->sched_scan_req->dev == wdev->netdev)) {
947 __cfg80211_stop_sched_scan(rdev, false);
948 }
949
950 rdev->opencount--;
951 wake_up(&rdev->dev_wait);
04a773ad
JB
952 break;
953 case NETDEV_UP:
4290cb4b 954 cfg80211_update_iface_num(rdev, wdev->iftype, 1);
667503dd 955 wdev_lock(wdev);
f2129354 956 switch (wdev->iftype) {
29cbe68c 957#ifdef CONFIG_CFG80211_WEXT
f2129354 958 case NL80211_IFTYPE_ADHOC:
fffd0934 959 cfg80211_ibss_wext_join(rdev, wdev);
04a773ad 960 break;
f2129354 961 case NL80211_IFTYPE_STATION:
fffd0934 962 cfg80211_mgd_wext_connect(rdev, wdev);
f2129354 963 break;
29cbe68c 964#endif
c80d545d 965#ifdef CONFIG_MAC80211_MESH
29cbe68c 966 case NL80211_IFTYPE_MESH_POINT:
c80d545d
JC
967 {
968 /* backward compat code... */
969 struct mesh_setup setup;
970 memcpy(&setup, &default_mesh_setup,
971 sizeof(setup));
972 /* back compat only needed for mesh_id */
973 setup.mesh_id = wdev->ssid;
974 setup.mesh_id_len = wdev->mesh_id_up_len;
975 if (wdev->mesh_id_up_len)
976 __cfg80211_join_mesh(rdev, dev,
977 &setup,
978 &default_mesh_config);
979 break;
980 }
981#endif
f2129354 982 default:
04a773ad 983 break;
f2129354 984 }
667503dd 985 wdev_unlock(wdev);
ad002395 986 rdev->opencount++;
bf6a0579
JO
987
988 /*
989 * Configure power management to the driver here so that its
990 * correctly set also after interface type changes etc.
991 */
5966f2dd
EP
992 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
993 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
bf6a0579 994 rdev->ops->set_power_mgmt)
e35e4d28
HG
995 if (rdev_set_power_mgmt(rdev, dev, wdev->ps,
996 wdev->ps_timeout)) {
bf6a0579
JO
997 /* assume this means it's off */
998 wdev->ps = false;
999 }
2a783c13 1000 break;
704232c2 1001 case NETDEV_UNREGISTER:
e40cbdac
JB
1002 /*
1003 * It is possible to get NETDEV_UNREGISTER
1004 * multiple times. To detect that, check
1005 * that the interface is still on the list
1006 * of registered interfaces, and only then
1007 * remove and clean it up.
1008 */
2a783c13 1009 if (!list_empty(&wdev->list)) {
704232c2 1010 sysfs_remove_link(&dev->dev.kobj, "phy80211");
5f2aa25e 1011 list_del_rcu(&wdev->list);
f5ea9120 1012 rdev->devlist_generation++;
2e161f78 1013 cfg80211_mlme_purge_registrations(wdev);
3d23e349 1014#ifdef CONFIG_CFG80211_WEXT
e40cbdac 1015 kfree(wdev->wext.keys);
fffd0934 1016#endif
e40cbdac 1017 }
5f2aa25e
JB
1018 /*
1019 * synchronise (so that we won't find this netdev
1020 * from other code any more) and then clear the list
1021 * head so that the above code can safely check for
1022 * !list_empty() to avoid double-cleanup.
1023 */
1024 synchronize_rcu();
1025 INIT_LIST_HEAD(&wdev->list);
1f6fc43e
DD
1026 /*
1027 * Ensure that all events have been processed and
1028 * freed.
1029 */
1030 cfg80211_process_wdev_events(wdev);
f9bef3df
BG
1031
1032 if (WARN_ON(wdev->current_bss)) {
1033 cfg80211_unhold_bss(wdev->current_bss);
1034 cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
1035 wdev->current_bss = NULL;
1036 }
704232c2 1037 break;
1f87f7d3 1038 case NETDEV_PRE_UP:
0b20633d
JB
1039 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
1040 return notifier_from_errno(-EOPNOTSUPP);
b6a55015
LC
1041 if (rfkill_blocked(rdev->rfkill))
1042 return notifier_from_errno(-ERFKILL);
1f87f7d3 1043 break;
6784c7db
ZG
1044 default:
1045 return NOTIFY_DONE;
704232c2
JB
1046 }
1047
6784c7db 1048 return NOTIFY_OK;
704232c2
JB
1049}
1050
1051static struct notifier_block cfg80211_netdev_notifier = {
1052 .notifier_call = cfg80211_netdev_notifier_call,
1053};
1054
463d0183
JB
1055static void __net_exit cfg80211_pernet_exit(struct net *net)
1056{
1057 struct cfg80211_registered_device *rdev;
1058
1059 rtnl_lock();
463d0183
JB
1060 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1061 if (net_eq(wiphy_net(&rdev->wiphy), net))
1062 WARN_ON(cfg80211_switch_netns(rdev, &init_net));
1063 }
463d0183
JB
1064 rtnl_unlock();
1065}
1066
1067static struct pernet_operations cfg80211_pernet_ops = {
1068 .exit = cfg80211_pernet_exit,
1069};
1070
1071static int __init cfg80211_init(void)
704232c2 1072{
b2e1b302
LR
1073 int err;
1074
463d0183
JB
1075 err = register_pernet_device(&cfg80211_pernet_ops);
1076 if (err)
1077 goto out_fail_pernet;
1078
b2e1b302 1079 err = wiphy_sysfs_init();
704232c2
JB
1080 if (err)
1081 goto out_fail_sysfs;
1082
1083 err = register_netdevice_notifier(&cfg80211_netdev_notifier);
1084 if (err)
1085 goto out_fail_notifier;
1086
55682965
JB
1087 err = nl80211_init();
1088 if (err)
1089 goto out_fail_nl80211;
1090
704232c2
JB
1091 ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
1092
b2e1b302
LR
1093 err = regulatory_init();
1094 if (err)
1095 goto out_fail_reg;
1096
e60d7443 1097 cfg80211_wq = create_singlethread_workqueue("cfg80211");
f00f188f
WY
1098 if (!cfg80211_wq) {
1099 err = -ENOMEM;
e60d7443 1100 goto out_fail_wq;
f00f188f 1101 }
e60d7443 1102
704232c2
JB
1103 return 0;
1104
e60d7443
AB
1105out_fail_wq:
1106 regulatory_exit();
b2e1b302
LR
1107out_fail_reg:
1108 debugfs_remove(ieee80211_debugfs_dir);
55682965
JB
1109out_fail_nl80211:
1110 unregister_netdevice_notifier(&cfg80211_netdev_notifier);
704232c2
JB
1111out_fail_notifier:
1112 wiphy_sysfs_exit();
1113out_fail_sysfs:
463d0183
JB
1114 unregister_pernet_device(&cfg80211_pernet_ops);
1115out_fail_pernet:
704232c2
JB
1116 return err;
1117}
3a462465 1118subsys_initcall(cfg80211_init);
704232c2 1119
f884e387 1120static void __exit cfg80211_exit(void)
704232c2
JB
1121{
1122 debugfs_remove(ieee80211_debugfs_dir);
55682965 1123 nl80211_exit();
704232c2
JB
1124 unregister_netdevice_notifier(&cfg80211_netdev_notifier);
1125 wiphy_sysfs_exit();
b2e1b302 1126 regulatory_exit();
463d0183 1127 unregister_pernet_device(&cfg80211_pernet_ops);
e60d7443 1128 destroy_workqueue(cfg80211_wq);
704232c2
JB
1129}
1130module_exit(cfg80211_exit);
This page took 0.895423 seconds and 5 git commands to generate.