Blame view

net/wireless/core.c 39.2 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
704232c27   Johannes Berg   [WIRELESS] cfg802...
2
3
4
  /*
   * This is the linux wireless configuration interface.
   *
5f2aa25e0   Johannes Berg   cfg80211: rcu-ify...
5
   * Copyright 2006-2010		Johannes Berg <johannes@sipsolutions.net>
2740f0cf8   Johannes Berg   cfg80211: add Int...
6
   * Copyright 2013-2014  Intel Mobile Communications GmbH
c4cbaf797   Luca Coelho   cfg80211: Add sup...
7
   * Copyright 2015-2017	Intel Deutschland GmbH
461ce35d5   Johannes Berg   cfg80211: reject ...
8
   * Copyright (C) 2018-2020 Intel Corporation
704232c27   Johannes Berg   [WIRELESS] cfg802...
9
   */
e9c0268f0   Joe Perches   net/wireless: Use...
10
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
704232c27   Johannes Berg   [WIRELESS] cfg802...
11
12
13
  #include <linux/if.h>
  #include <linux/module.h>
  #include <linux/err.h>
704232c27   Johannes Berg   [WIRELESS] cfg802...
14
  #include <linux/list.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
704232c27   Johannes Berg   [WIRELESS] cfg802...
16
17
18
19
  #include <linux/nl80211.h>
  #include <linux/debugfs.h>
  #include <linux/notifier.h>
  #include <linux/device.h>
16a832e78   Zhu Yi   cfg80211: allow c...
20
  #include <linux/etherdevice.h>
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
21
  #include <linux/rtnetlink.h>
d43c36dc6   Alexey Dobriyan   headers: remove s...
22
  #include <linux/sched.h>
704232c27   Johannes Berg   [WIRELESS] cfg802...
23
24
  #include <net/genetlink.h>
  #include <net/cfg80211.h>
556829657   Johannes Berg   [NL80211]: add ne...
25
  #include "nl80211.h"
704232c27   Johannes Berg   [WIRELESS] cfg802...
26
27
  #include "core.h"
  #include "sysfs.h"
1ac61302d   Luis R. Rodriguez   mac80211/cfg80211...
28
  #include "debugfs.h"
a9a11622c   Johannes Berg   cfg80211: self-co...
29
  #include "wext-compat.h"
e35e4d28b   Hila Gonen   cfg80211: add wra...
30
  #include "rdev-ops.h"
704232c27   Johannes Berg   [WIRELESS] cfg802...
31
32
33
34
35
36
37
  
  /* name for sysfs, %d is appended */
  #define PHY_NAME "phy"
  
  MODULE_AUTHOR("Johannes Berg");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("wireless configuration support");
fb4e15688   Marcel Holtmann   nl80211: Add gene...
38
  MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
704232c27   Johannes Berg   [WIRELESS] cfg802...
39

5fe231e87   Johannes Berg   cfg80211: vastly ...
40
  /* RCU-protected (and RTNL for writers) */
79c97e97a   Johannes Berg   cfg80211: clean u...
41
  LIST_HEAD(cfg80211_rdev_list);
f5ea9120b   Johannes Berg   nl80211: add gene...
42
  int cfg80211_rdev_list_generation;
a1794390f   Luis R. Rodriguez   cfg80211: rename ...
43

704232c27   Johannes Berg   [WIRELESS] cfg802...
44
45
  /* for debugfs */
  static struct dentry *ieee80211_debugfs_dir;
e60d7443e   Alban Browaeys   wireless : use a ...
46
47
  /* for the cleanup, scan and event works */
  struct workqueue_struct *cfg80211_wq;
40db6c77a   Amitkumar Karwar   cfg80211: module_...
48
49
50
51
  static bool cfg80211_disable_40mhz_24ghz;
  module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
  MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
  		 "Disable 40MHz support in the 2.4GHz band");
79c97e97a   Johannes Berg   cfg80211: clean u...
52
  struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
556829657   Johannes Berg   [NL80211]: add ne...
53
  {
79c97e97a   Johannes Berg   cfg80211: clean u...
54
  	struct cfg80211_registered_device *result = NULL, *rdev;
556829657   Johannes Berg   [NL80211]: add ne...
55

5fe231e87   Johannes Berg   cfg80211: vastly ...
56
  	ASSERT_RTNL();
761cf7ecf   Luis R. Rodriguez   cfg80211: add ass...
57

79c97e97a   Johannes Berg   cfg80211: clean u...
58
59
60
  	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
  		if (rdev->wiphy_idx == wiphy_idx) {
  			result = rdev;
556829657   Johannes Berg   [NL80211]: add ne...
61
62
63
64
65
66
  			break;
  		}
  	}
  
  	return result;
  }
806a9e396   Luis R. Rodriguez   cfg80211: make re...
67
68
  int get_wiphy_idx(struct wiphy *wiphy)
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
69
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
f41737669   Johannes Berg   cfg80211: remove ...
70

79c97e97a   Johannes Berg   cfg80211: clean u...
71
  	return rdev->wiphy_idx;
806a9e396   Luis R. Rodriguez   cfg80211: make re...
72
  }
806a9e396   Luis R. Rodriguez   cfg80211: make re...
73
74
  struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
  {
79c97e97a   Johannes Berg   cfg80211: clean u...
75
  	struct cfg80211_registered_device *rdev;
806a9e396   Luis R. Rodriguez   cfg80211: make re...
76

5fe231e87   Johannes Berg   cfg80211: vastly ...
77
  	ASSERT_RTNL();
806a9e396   Luis R. Rodriguez   cfg80211: make re...
78

79c97e97a   Johannes Berg   cfg80211: clean u...
79
80
  	rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
  	if (!rdev)
806a9e396   Luis R. Rodriguez   cfg80211: make re...
81
  		return NULL;
79c97e97a   Johannes Berg   cfg80211: clean u...
82
  	return &rdev->wiphy;
806a9e396   Luis R. Rodriguez   cfg80211: make re...
83
  }
1998d90ad   Ben Greear   cfg80211: support...
84
85
  static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
  				   const char *newname)
556829657   Johannes Berg   [NL80211]: add ne...
86
  {
79c97e97a   Johannes Berg   cfg80211: clean u...
87
  	struct cfg80211_registered_device *rdev2;
1998d90ad   Ben Greear   cfg80211: support...
88
  	int wiphy_idx, taken = -1, digits;
556829657   Johannes Berg   [NL80211]: add ne...
89

5fe231e87   Johannes Berg   cfg80211: vastly ...
90
  	ASSERT_RTNL();
2940bb69f   Eric W. Biederman   wireless: Add mis...
91

a7cfebcb7   Johannes Berg   cfg80211: limit w...
92
93
  	if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN)
  		return -EINVAL;
7623225f9   Johannes Berg   Revert "wireless:...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  	/* prohibit calling the thing phy%d when %d is not its number */
  	sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
  	if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
  		/* count number of places needed to print wiphy_idx */
  		digits = 1;
  		while (wiphy_idx /= 10)
  			digits++;
  		/*
  		 * deny the name if it is phy<idx> where <idx> is printed
  		 * without leading zeroes. taken == strlen(newname) here
  		 */
  		if (taken == strlen(PHY_NAME) + digits)
  			return -EINVAL;
  	}
1998d90ad   Ben Greear   cfg80211: support...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  	/* Ensure another device does not already have this name. */
  	list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
  		if (strcmp(newname, wiphy_name(&rdev2->wiphy)) == 0)
  			return -EINVAL;
  
  	return 0;
  }
  
  int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
  			char *newname)
  {
  	int result;
  
  	ASSERT_RTNL();
7623225f9   Johannes Berg   Revert "wireless:...
122

2940bb69f   Eric W. Biederman   wireless: Add mis...
123
  	/* Ignore nop renames */
1998d90ad   Ben Greear   cfg80211: support...
124
  	if (strcmp(newname, wiphy_name(&rdev->wiphy)) == 0)
4bbf4d565   Johannes Berg   cfg80211: fix loc...
125
  		return 0;
2940bb69f   Eric W. Biederman   wireless: Add mis...
126

1998d90ad   Ben Greear   cfg80211: support...
127
128
129
  	result = cfg80211_dev_check_name(rdev, newname);
  	if (result < 0)
  		return result;
556829657   Johannes Berg   [NL80211]: add ne...
130

556829657   Johannes Berg   [NL80211]: add ne...
131
132
  	result = device_rename(&rdev->wiphy.dev, newname);
  	if (result)
4bbf4d565   Johannes Berg   cfg80211: fix loc...
133
  		return result;
556829657   Johannes Berg   [NL80211]: add ne...
134

0bbab5f03   Johannes Berg   cfg80211: fix deb...
135
  	if (!IS_ERR_OR_NULL(rdev->wiphy.debugfsdir))
d82574a8e   Greg Kroah-Hartman   cfg80211: no need...
136
137
138
  		debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
  			       rdev->wiphy.debugfsdir,
  			       rdev->wiphy.debugfsdir->d_parent, newname);
556829657   Johannes Berg   [NL80211]: add ne...
139

3bb205567   Johannes Berg   cfg80211: send ev...
140
  	nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
556829657   Johannes Berg   [NL80211]: add ne...
141

4bbf4d565   Johannes Berg   cfg80211: fix loc...
142
  	return 0;
556829657   Johannes Berg   [NL80211]: add ne...
143
  }
463d01832   Johannes Berg   cfg80211: make aw...
144
145
146
147
148
  int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
  			  struct net *net)
  {
  	struct wireless_dev *wdev;
  	int err = 0;
5be83de54   Johannes Berg   cfg80211: convert...
149
  	if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
463d01832   Johannes Berg   cfg80211: make aw...
150
  		return -EOPNOTSUPP;
53873f134   Johannes Berg   cfg80211: make wd...
151
  	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
ba22fb5b2   Johannes Berg   nl80211: don't as...
152
153
  		if (!wdev->netdev)
  			continue;
463d01832   Johannes Berg   cfg80211: make aw...
154
155
156
157
158
159
160
161
162
163
  		wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
  		err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
  		if (err)
  			break;
  		wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
  	}
  
  	if (err) {
  		/* failed -- clean up to old netns */
  		net = wiphy_net(&rdev->wiphy);
53873f134   Johannes Berg   cfg80211: make wd...
164
165
  		list_for_each_entry_continue_reverse(wdev,
  						     &rdev->wiphy.wdev_list,
463d01832   Johannes Berg   cfg80211: make aw...
166
  						     list) {
ba22fb5b2   Johannes Berg   nl80211: don't as...
167
168
  			if (!wdev->netdev)
  				continue;
463d01832   Johannes Berg   cfg80211: make aw...
169
170
171
172
173
174
  			wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
  			err = dev_change_net_namespace(wdev->netdev, net,
  							"wlan%d");
  			WARN_ON(err);
  			wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
  		}
046007949   Johannes Berg   cfg80211: support...
175
176
  
  		return err;
463d01832   Johannes Berg   cfg80211: make aw...
177
  	}
c90b670b5   Martin Willi   nl80211: announce...
178
179
180
181
182
183
  	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
  		if (!wdev->netdev)
  			continue;
  		nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
  	}
  	nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
463d01832   Johannes Berg   cfg80211: make aw...
184
  	wiphy_net_set(&rdev->wiphy, net);
046007949   Johannes Berg   cfg80211: support...
185
186
  	err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev));
  	WARN_ON(err);
c90b670b5   Martin Willi   nl80211: announce...
187
188
189
190
191
192
  	nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
  	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
  		if (!wdev->netdev)
  			continue;
  		nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
  	}
046007949   Johannes Berg   cfg80211: support...
193
  	return 0;
463d01832   Johannes Berg   cfg80211: make aw...
194
  }
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
195
196
  static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
  {
79c97e97a   Johannes Berg   cfg80211: clean u...
197
  	struct cfg80211_registered_device *rdev = data;
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
198

e35e4d28b   Hila Gonen   cfg80211: add wra...
199
  	rdev_rfkill_poll(rdev);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
200
  }
f9f475292   Johannes Berg   cfg80211: always ...
201
202
203
  void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
  			      struct wireless_dev *wdev)
  {
5fe231e87   Johannes Berg   cfg80211: vastly ...
204
  	ASSERT_RTNL();
f9f475292   Johannes Berg   cfg80211: always ...
205
206
207
  
  	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
  		return;
73c7da3da   Arend Van Spriel   cfg80211: add gen...
208
  	if (!wdev_running(wdev))
f9f475292   Johannes Berg   cfg80211: always ...
209
210
211
  		return;
  
  	rdev_stop_p2p_device(rdev, wdev);
73c7da3da   Arend Van Spriel   cfg80211: add gen...
212
  	wdev->is_running = false;
f9f475292   Johannes Berg   cfg80211: always ...
213
214
  
  	rdev->opencount--;
a617302c5   Johannes Berg   cfg80211: fix sca...
215
  	if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
c8cb5b854   Tova Mussai   nl80211/cfg80211:...
216
217
218
  		if (WARN_ON(!rdev->scan_req->notified &&
  			    (!rdev->int_scan_req ||
  			     !rdev->int_scan_req->notified)))
1d76250bd   Avraham Stern   nl80211: support ...
219
  			rdev->scan_req->info.aborted = true;
f9d15d162   Johannes Berg   cfg80211: send sc...
220
  		___cfg80211_scan_done(rdev, false);
a617302c5   Johannes Berg   cfg80211: fix sca...
221
  	}
f9f475292   Johannes Berg   cfg80211: always ...
222
  }
cb3b7d876   Ayala Beker   cfg80211: add sta...
223
224
225
226
227
228
229
  void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
  		       struct wireless_dev *wdev)
  {
  	ASSERT_RTNL();
  
  	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
  		return;
73c7da3da   Arend Van Spriel   cfg80211: add gen...
230
  	if (!wdev_running(wdev))
cb3b7d876   Ayala Beker   cfg80211: add sta...
231
232
233
  		return;
  
  	rdev_stop_nan(rdev, wdev);
73c7da3da   Arend Van Spriel   cfg80211: add gen...
234
  	wdev->is_running = false;
cb3b7d876   Ayala Beker   cfg80211: add sta...
235
236
237
  
  	rdev->opencount--;
  }
f6837ba8c   Johannes Berg   mac80211: handle ...
238
  void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
239
  {
f6837ba8c   Johannes Berg   mac80211: handle ...
240
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
241
  	struct wireless_dev *wdev;
f6837ba8c   Johannes Berg   mac80211: handle ...
242
  	ASSERT_RTNL();
f9f475292   Johannes Berg   cfg80211: always ...
243

53873f134   Johannes Berg   cfg80211: make wd...
244
  	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
98104fded   Johannes Berg   cfg80211: add P2P...
245
  		if (wdev->netdev) {
ba22fb5b2   Johannes Berg   nl80211: don't as...
246
  			dev_close(wdev->netdev);
98104fded   Johannes Berg   cfg80211: add P2P...
247
248
249
250
251
  			continue;
  		}
  		/* otherwise, check iftype */
  		switch (wdev->iftype) {
  		case NL80211_IFTYPE_P2P_DEVICE:
f9f475292   Johannes Berg   cfg80211: always ...
252
  			cfg80211_stop_p2p_device(rdev, wdev);
98104fded   Johannes Berg   cfg80211: add P2P...
253
  			break;
cb3b7d876   Ayala Beker   cfg80211: add sta...
254
255
256
  		case NL80211_IFTYPE_NAN:
  			cfg80211_stop_nan(rdev, wdev);
  			break;
98104fded   Johannes Berg   cfg80211: add P2P...
257
258
259
260
  		default:
  			break;
  		}
  	}
f6837ba8c   Johannes Berg   mac80211: handle ...
261
262
  }
  EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
263

f6837ba8c   Johannes Berg   mac80211: handle ...
264
265
266
267
268
269
270
271
272
  static int cfg80211_rfkill_set_block(void *data, bool blocked)
  {
  	struct cfg80211_registered_device *rdev = data;
  
  	if (!blocked)
  		return 0;
  
  	rtnl_lock();
  	cfg80211_shutdown_all_interfaces(&rdev->wiphy);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
273
274
275
276
  	rtnl_unlock();
  
  	return 0;
  }
3cfe91c4c   Johannes Berg   cfg80211: always ...
277
  static void cfg80211_rfkill_block_work(struct work_struct *work)
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
278
  {
79c97e97a   Johannes Berg   cfg80211: clean u...
279
  	struct cfg80211_registered_device *rdev;
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
280

3cfe91c4c   Johannes Berg   cfg80211: always ...
281
282
283
  	rdev = container_of(work, struct cfg80211_registered_device,
  			    rfkill_block);
  	cfg80211_rfkill_set_block(rdev, true);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
284
  }
667503ddc   Johannes Berg   cfg80211: fix loc...
285
286
287
  static void cfg80211_event_work(struct work_struct *work)
  {
  	struct cfg80211_registered_device *rdev;
667503ddc   Johannes Berg   cfg80211: fix loc...
288
289
290
291
292
  
  	rdev = container_of(work, struct cfg80211_registered_device,
  			    event_work);
  
  	rtnl_lock();
3d54d2551   Johannes Berg   cfg80211: clean u...
293
  	cfg80211_process_rdev_events(rdev);
667503ddc   Johannes Berg   cfg80211: fix loc...
294
295
  	rtnl_unlock();
  }
78f22b6a3   Johannes Berg   cfg80211: allow u...
296
297
  void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
  {
ab81007a7   Johannes Berg   cfg80211: simplif...
298
  	struct wireless_dev *wdev, *tmp;
78f22b6a3   Johannes Berg   cfg80211: allow u...
299
300
  
  	ASSERT_RTNL();
ab81007a7   Johannes Berg   cfg80211: simplif...
301
302
303
  	list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
  		if (wdev->nl_owner_dead)
  			rdev_del_virtual_intf(rdev, wdev);
78f22b6a3   Johannes Berg   cfg80211: allow u...
304
  	}
78f22b6a3   Johannes Berg   cfg80211: allow u...
305
306
307
308
309
310
311
312
313
314
315
316
317
  }
  
  static void cfg80211_destroy_iface_wk(struct work_struct *work)
  {
  	struct cfg80211_registered_device *rdev;
  
  	rdev = container_of(work, struct cfg80211_registered_device,
  			    destroy_work);
  
  	rtnl_lock();
  	cfg80211_destroy_ifaces(rdev);
  	rtnl_unlock();
  }
93a1e86ce   Jukka Rissanen   nl80211: Stop sch...
318
319
320
  static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
  {
  	struct cfg80211_registered_device *rdev;
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
321
  	struct cfg80211_sched_scan_request *req, *tmp;
93a1e86ce   Jukka Rissanen   nl80211: Stop sch...
322
323
324
325
326
  
  	rdev = container_of(work, struct cfg80211_registered_device,
  			   sched_scan_stop_wk);
  
  	rtnl_lock();
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
327
328
329
330
  	list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) {
  		if (req->nl_owner_dead)
  			cfg80211_stop_sched_scan_req(rdev, req, false);
  	}
93a1e86ce   Jukka Rissanen   nl80211: Stop sch...
331
332
  	rtnl_unlock();
  }
897667273   Vasanthakumar Thiagarajan   cfg80211: Share C...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  static void cfg80211_propagate_radar_detect_wk(struct work_struct *work)
  {
  	struct cfg80211_registered_device *rdev;
  
  	rdev = container_of(work, struct cfg80211_registered_device,
  			    propagate_radar_detect_wk);
  
  	rtnl_lock();
  
  	regulatory_propagate_dfs_state(&rdev->wiphy, &rdev->radar_chandef,
  				       NL80211_DFS_UNAVAILABLE,
  				       NL80211_RADAR_DETECTED);
  
  	rtnl_unlock();
  }
  
  static void cfg80211_propagate_cac_done_wk(struct work_struct *work)
  {
  	struct cfg80211_registered_device *rdev;
  
  	rdev = container_of(work, struct cfg80211_registered_device,
  			    propagate_cac_done_wk);
  
  	rtnl_lock();
  
  	regulatory_propagate_dfs_state(&rdev->wiphy, &rdev->cac_done_chandef,
  				       NL80211_DFS_AVAILABLE,
  				       NL80211_RADAR_CAC_FINISHED);
  
  	rtnl_unlock();
  }
704232c27   Johannes Berg   [WIRELESS] cfg802...
364
  /* exported functions */
1998d90ad   Ben Greear   cfg80211: support...
365
366
  struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
  			   const char *requested_name)
704232c27   Johannes Berg   [WIRELESS] cfg802...
367
  {
73810b77d   Johannes Berg   cfg80211: use ato...
368
  	static atomic_t wiphy_counter = ATOMIC_INIT(0);
7623225f9   Johannes Berg   Revert "wireless:...
369
370
  
  	struct cfg80211_registered_device *rdev;
704232c27   Johannes Berg   [WIRELESS] cfg802...
371
  	int alloc_size;
0b20633d9   Johannes Berg   cfg80211: disallo...
372
373
374
375
376
377
378
  	WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
  	WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
  	WARN_ON(ops->connect && !ops->disconnect);
  	WARN_ON(ops->join_ibss && !ops->leave_ibss);
  	WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
  	WARN_ON(ops->add_station && !ops->del_station);
  	WARN_ON(ops->add_mpath && !ops->del_mpath);
29cbe68c5   Johannes Berg   cfg80211/mac80211...
379
  	WARN_ON(ops->join_mesh && !ops->leave_mesh);
de3bb771f   Ola Olsson   cfg80211: add mor...
380
381
382
383
384
385
386
387
  	WARN_ON(ops->start_p2p_device && !ops->stop_p2p_device);
  	WARN_ON(ops->start_ap && !ops->stop_ap);
  	WARN_ON(ops->join_ocb && !ops->leave_ocb);
  	WARN_ON(ops->suspend && !ops->resume);
  	WARN_ON(ops->sched_scan_start && !ops->sched_scan_stop);
  	WARN_ON(ops->remain_on_channel && !ops->cancel_remain_on_channel);
  	WARN_ON(ops->tdls_channel_switch && !ops->tdls_cancel_channel_switch);
  	WARN_ON(ops->add_tx_ts && !ops->del_tx_ts);
41ade00f2   Johannes Berg   cfg80211/nl80211:...
388

79c97e97a   Johannes Berg   cfg80211: clean u...
389
  	alloc_size = sizeof(*rdev) + sizeof_priv;
704232c27   Johannes Berg   [WIRELESS] cfg802...
390

79c97e97a   Johannes Berg   cfg80211: clean u...
391
392
  	rdev = kzalloc(alloc_size, GFP_KERNEL);
  	if (!rdev)
704232c27   Johannes Berg   [WIRELESS] cfg802...
393
  		return NULL;
79c97e97a   Johannes Berg   cfg80211: clean u...
394
  	rdev->ops = ops;
704232c27   Johannes Berg   [WIRELESS] cfg802...
395

73810b77d   Johannes Berg   cfg80211: use ato...
396
  	rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
a4d73ee16   Johannes Berg   [WIRELESS] cfg802...
397

f41737669   Johannes Berg   cfg80211: remove ...
398
  	if (unlikely(rdev->wiphy_idx < 0)) {
7623225f9   Johannes Berg   Revert "wireless:...
399
  		/* ugh, wrapped! */
73810b77d   Johannes Berg   cfg80211: use ato...
400
  		atomic_dec(&wiphy_counter);
79c97e97a   Johannes Berg   cfg80211: clean u...
401
  		kfree(rdev);
704232c27   Johannes Berg   [WIRELESS] cfg802...
402
403
  		return NULL;
  	}
704232c27   Johannes Berg   [WIRELESS] cfg802...
404

9b881963c   Johannes Berg   cfg80211: make wi...
405
406
  	/* atomic_inc_return makes it start at 1, make it start at 0 */
  	rdev->wiphy_idx--;
7623225f9   Johannes Berg   Revert "wireless:...
407
  	/* give it a proper name */
1998d90ad   Ben Greear   cfg80211: support...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
  	if (requested_name && requested_name[0]) {
  		int rv;
  
  		rtnl_lock();
  		rv = cfg80211_dev_check_name(rdev, requested_name);
  
  		if (rv < 0) {
  			rtnl_unlock();
  			goto use_default_name;
  		}
  
  		rv = dev_set_name(&rdev->wiphy.dev, "%s", requested_name);
  		rtnl_unlock();
  		if (rv)
  			goto use_default_name;
  	} else {
59b179b48   Johannes Berg   cfg80211: check d...
424
  		int rv;
1998d90ad   Ben Greear   cfg80211: support...
425
426
427
428
429
430
431
  use_default_name:
  		/* NOTE:  This is *probably* safe w/out holding rtnl because of
  		 * the restrictions on phy names.  Probably this call could
  		 * fail if some other part of the kernel (re)named a device
  		 * phyX.  But, might should add some locking and check return
  		 * value, and use a different name if this one exists?
  		 */
59b179b48   Johannes Berg   cfg80211: check d...
432
433
434
435
436
  		rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
  		if (rv < 0) {
  			kfree(rdev);
  			return NULL;
  		}
1998d90ad   Ben Greear   cfg80211: support...
437
  	}
7623225f9   Johannes Berg   Revert "wireless:...
438

53873f134   Johannes Berg   cfg80211: make wd...
439
  	INIT_LIST_HEAD(&rdev->wiphy.wdev_list);
37c73b5f3   Ben Greear   cfg80211: allow r...
440
441
  	INIT_LIST_HEAD(&rdev->beacon_registrations);
  	spin_lock_init(&rdev->beacon_registrations_lock);
79c97e97a   Johannes Berg   cfg80211: clean u...
442
443
  	spin_lock_init(&rdev->bss_lock);
  	INIT_LIST_HEAD(&rdev->bss_list);
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
444
  	INIT_LIST_HEAD(&rdev->sched_scan_req_list);
79c97e97a   Johannes Berg   cfg80211: clean u...
445
  	INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
04f39047a   Simon Wunderlich   nl80211/cfg80211:...
446
447
  	INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
  			  cfg80211_dfs_channels_update_work);
3d23e349d   Johannes Berg   wext: refactor
448
449
450
  #ifdef CONFIG_CFG80211_WEXT
  	rdev->wiphy.wext = &cfg80211_wext_handler;
  #endif
79c97e97a   Johannes Berg   cfg80211: clean u...
451
452
453
  	device_initialize(&rdev->wiphy.dev);
  	rdev->wiphy.dev.class = &ieee80211_class;
  	rdev->wiphy.dev.platform_data = rdev;
9f0e13546   Fu, Zhonghui   net/wireless: ena...
454
  	device_enable_async_suspend(&rdev->wiphy.dev);
79c97e97a   Johannes Berg   cfg80211: clean u...
455

78f22b6a3   Johannes Berg   cfg80211: allow u...
456
  	INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
93a1e86ce   Jukka Rissanen   nl80211: Stop sch...
457
  	INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
b34939b98   Arend Van Spriel   cfg80211: add req...
458
  	INIT_WORK(&rdev->sched_scan_res_wk, cfg80211_sched_scan_results_wk);
897667273   Vasanthakumar Thiagarajan   cfg80211: Share C...
459
460
461
  	INIT_WORK(&rdev->propagate_radar_detect_wk,
  		  cfg80211_propagate_radar_detect_wk);
  	INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
79ea1e12c   Johannes Berg   cfg80211: fix man...
462
463
  	INIT_WORK(&rdev->mgmt_registrations_update_wk,
  		  cfg80211_mgmt_registrations_update_wk);
78f22b6a3   Johannes Berg   cfg80211: allow u...
464

5be83de54   Johannes Berg   cfg80211: convert...
465
466
467
  #ifdef CONFIG_CFG80211_DEFAULT_PS
  	rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
  #endif
16cb9d42b   Johannes Berg   cfg80211: allow d...
468

463d01832   Johannes Berg   cfg80211: make aw...
469
  	wiphy_net_set(&rdev->wiphy, &init_net);
79c97e97a   Johannes Berg   cfg80211: clean u...
470
471
472
473
474
475
  	rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
  	rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev),
  				   &rdev->wiphy.dev, RFKILL_TYPE_WLAN,
  				   &rdev->rfkill_ops, rdev);
  
  	if (!rdev->rfkill) {
4f488fbca   Eric Biggers   cfg80211: fix mem...
476
  		wiphy_free(&rdev->wiphy);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
477
478
  		return NULL;
  	}
3cfe91c4c   Johannes Berg   cfg80211: always ...
479
  	INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work);
79c97e97a   Johannes Berg   cfg80211: clean u...
480
481
  	INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
  	INIT_WORK(&rdev->event_work, cfg80211_event_work);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
482

ad002395f   Johannes Berg   cfg80211: fix dan...
483
  	init_waitqueue_head(&rdev->dev_wait);
b9a5f8cab   Jouni Malinen   nl80211: Add set/...
484
485
486
487
488
  	/*
  	 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
  	 * Fragmentation and RTS threshold are disabled by default with the
  	 * special -1 value.
  	 */
79c97e97a   Johannes Berg   cfg80211: clean u...
489
490
491
492
  	rdev->wiphy.retry_short = 7;
  	rdev->wiphy.retry_long = 4;
  	rdev->wiphy.frag_threshold = (u32) -1;
  	rdev->wiphy.rts_threshold = (u32) -1;
81077e82c   Lukáš Turek   nl80211: Add new ...
493
  	rdev->wiphy.coverage_class = 0;
b9a5f8cab   Jouni Malinen   nl80211: Add set/...
494

9a774c78e   Andrei Otcheretianski   cfg80211: Support...
495
  	rdev->wiphy.max_num_csa_counters = 1;
3b06d2779   Avraham Stern   cfg80211: Add mul...
496
497
  	rdev->wiphy.max_sched_scan_plans = 1;
  	rdev->wiphy.max_sched_scan_plan_interval = U32_MAX;
79c97e97a   Johannes Berg   cfg80211: clean u...
498
  	return &rdev->wiphy;
704232c27   Johannes Berg   [WIRELESS] cfg802...
499
  }
1998d90ad   Ben Greear   cfg80211: support...
500
  EXPORT_SYMBOL(wiphy_new_nm);
704232c27   Johannes Berg   [WIRELESS] cfg802...
501

7527a782e   Johannes Berg   cfg80211: adverti...
502
503
504
505
  static int wiphy_verify_combinations(struct wiphy *wiphy)
  {
  	const struct ieee80211_iface_combination *c;
  	int i, j;
7527a782e   Johannes Berg   cfg80211: adverti...
506
507
508
509
510
  	for (i = 0; i < wiphy->n_iface_combinations; i++) {
  		u32 cnt = 0;
  		u16 all_iftypes = 0;
  
  		c = &wiphy->iface_combinations[i];
11c4a075d   Simon Wunderlich   cfg80211: check r...
511
512
513
514
515
  		/*
  		 * Combinations with just one interface aren't real,
  		 * however we make an exception for DFS.
  		 */
  		if (WARN_ON((c->max_interfaces < 2) && !c->radar_detect_widths))
7527a782e   Johannes Berg   cfg80211: adverti...
516
517
518
519
520
  			return -EINVAL;
  
  		/* Need at least one channel */
  		if (WARN_ON(!c->num_different_channels))
  			return -EINVAL;
d4e50c591   Michal Kazior   cfg80211: add cha...
521
522
523
524
525
526
527
  		/*
  		 * Put a sane limit on maximum number of different
  		 * channels to simplify channel accounting code.
  		 */
  		if (WARN_ON(c->num_different_channels >
  				CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
  			return -EINVAL;
11c4a075d   Simon Wunderlich   cfg80211: check r...
528
529
530
531
  		/* DFS only works on one channel. */
  		if (WARN_ON(c->radar_detect_widths &&
  			    (c->num_different_channels > 1)))
  			return -EINVAL;
7527a782e   Johannes Berg   cfg80211: adverti...
532
533
534
535
536
  		if (WARN_ON(!c->n_limits))
  			return -EINVAL;
  
  		for (j = 0; j < c->n_limits; j++) {
  			u16 types = c->limits[j].types;
b6a550156   Luciano Coelho   cfg80211/mac80211...
537
  			/* interface types shouldn't overlap */
7527a782e   Johannes Berg   cfg80211: adverti...
538
539
540
541
542
543
544
545
546
547
  			if (WARN_ON(types & all_iftypes))
  				return -EINVAL;
  			all_iftypes |= types;
  
  			if (WARN_ON(!c->limits[j].max))
  				return -EINVAL;
  
  			/* Shouldn't list software iftypes in combinations! */
  			if (WARN_ON(wiphy->software_iftypes & types))
  				return -EINVAL;
98104fded   Johannes Berg   cfg80211: add P2P...
548
549
550
551
  			/* Only a single P2P_DEVICE can be allowed */
  			if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) &&
  				    c->limits[j].max > 1))
  				return -EINVAL;
cb3b7d876   Ayala Beker   cfg80211: add sta...
552
553
554
555
  			/* Only a single NAN can be allowed */
  			if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) &&
  				    c->limits[j].max > 1))
  				return -EINVAL;
56271da29   Johannes Berg   cfg80211: disallo...
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  			/*
  			 * This isn't well-defined right now. If you have an
  			 * IBSS interface, then its beacon interval may change
  			 * by joining other networks, and nothing prevents it
  			 * from doing that.
  			 * So technically we probably shouldn't even allow AP
  			 * and IBSS in the same interface, but it seems that
  			 * some drivers support that, possibly only with fixed
  			 * beacon intervals for IBSS.
  			 */
  			if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) &&
  				    c->beacon_int_min_gcd)) {
  				return -EINVAL;
  			}
7527a782e   Johannes Berg   cfg80211: adverti...
570
571
572
573
574
575
576
577
  			cnt += c->limits[j].max;
  			/*
  			 * Don't advertise an unsupported type
  			 * in a combination.
  			 */
  			if (WARN_ON((wiphy->interface_modes & types) != types))
  				return -EINVAL;
  		}
8f2054238   Johannes Berg   wireless: depreca...
578
579
580
581
  #ifndef CONFIG_WIRELESS_WDS
  		if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS)))
  			return -EINVAL;
  #endif
7527a782e   Johannes Berg   cfg80211: adverti...
582
583
584
585
586
587
588
  		/* You can't even choose that many! */
  		if (WARN_ON(cnt < c->max_interfaces))
  			return -EINVAL;
  	}
  
  	return 0;
  }
704232c27   Johannes Berg   [WIRELESS] cfg802...
589
590
  int wiphy_register(struct wiphy *wiphy)
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
591
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
704232c27   Johannes Berg   [WIRELESS] cfg802...
592
  	int res;
57fbcce37   Johannes Berg   cfg80211: remove ...
593
  	enum nl80211_band band;
8318d78a4   Johannes Berg   cfg80211 API for ...
594
595
596
  	struct ieee80211_supported_band *sband;
  	bool have_band = false;
  	int i;
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
597
  	u16 ifmodes = wiphy->interface_modes;
dfb89c56a   Johannes Berg   cfg80211: don't a...
598
  #ifdef CONFIG_PM
964dc9e2c   Johannes Berg   cfg80211: take Wo...
599
600
601
602
603
604
605
  	if (WARN_ON(wiphy->wowlan &&
  		    (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
  		    !(wiphy->wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
  		return -EINVAL;
  	if (WARN_ON(wiphy->wowlan &&
  		    !wiphy->wowlan->flags && !wiphy->wowlan->n_patterns &&
  		    !wiphy->wowlan->tcp))
77dbbb138   Johannes Berg   nl80211: advertis...
606
  		return -EINVAL;
dfb89c56a   Johannes Berg   cfg80211: don't a...
607
  #endif
1057d35ed   Arik Nemtsov   cfg80211: introdu...
608
609
610
611
  	if (WARN_ON((wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
  		    (!rdev->ops->tdls_channel_switch ||
  		     !rdev->ops->tdls_cancel_channel_switch)))
  		return -EINVAL;
77dbbb138   Johannes Berg   nl80211: advertis...
612

cb3b7d876   Ayala Beker   cfg80211: add sta...
613
  	if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN)) &&
a442b761b   Ayala Beker   cfg80211: add add...
614
  		    (!rdev->ops->start_nan || !rdev->ops->stop_nan ||
8585989d1   Luca Coelho   cfg80211: fix NAN...
615
616
  		     !rdev->ops->add_nan_func || !rdev->ops->del_nan_func ||
  		     !(wiphy->nan_supported_bands & BIT(NL80211_BAND_2GHZ)))))
cb3b7d876   Ayala Beker   cfg80211: add sta...
617
  		return -EINVAL;
8f2054238   Johannes Berg   wireless: depreca...
618
619
620
621
  #ifndef CONFIG_WIRELESS_WDS
  	if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))
  		return -EINVAL;
  #endif
9bb7e0f24   Johannes Berg   cfg80211: add pee...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
  	if (WARN_ON(wiphy->pmsr_capa && !wiphy->pmsr_capa->ftm.supported))
  		return -EINVAL;
  
  	if (wiphy->pmsr_capa && wiphy->pmsr_capa->ftm.supported) {
  		if (WARN_ON(!wiphy->pmsr_capa->ftm.asap &&
  			    !wiphy->pmsr_capa->ftm.non_asap))
  			return -EINVAL;
  		if (WARN_ON(!wiphy->pmsr_capa->ftm.preambles ||
  			    !wiphy->pmsr_capa->ftm.bandwidths))
  			return -EINVAL;
  		if (WARN_ON(wiphy->pmsr_capa->ftm.preambles &
  				~(BIT(NL80211_PREAMBLE_LEGACY) |
  				  BIT(NL80211_PREAMBLE_HT) |
  				  BIT(NL80211_PREAMBLE_VHT) |
efb5520d0   Avraham Stern   nl80211/cfg80211:...
636
  				  BIT(NL80211_PREAMBLE_HE) |
9bb7e0f24   Johannes Berg   cfg80211: add pee...
637
638
  				  BIT(NL80211_PREAMBLE_DMG))))
  			return -EINVAL;
efb5520d0   Avraham Stern   nl80211/cfg80211:...
639
640
641
642
643
  		if (WARN_ON((wiphy->pmsr_capa->ftm.trigger_based ||
  			     wiphy->pmsr_capa->ftm.non_trigger_based) &&
  			    !(wiphy->pmsr_capa->ftm.preambles &
  			      BIT(NL80211_PREAMBLE_HE))))
  			return -EINVAL;
9bb7e0f24   Johannes Berg   cfg80211: add pee...
644
645
646
647
648
649
650
651
652
653
654
  		if (WARN_ON(wiphy->pmsr_capa->ftm.bandwidths &
  				~(BIT(NL80211_CHAN_WIDTH_20_NOHT) |
  				  BIT(NL80211_CHAN_WIDTH_20) |
  				  BIT(NL80211_CHAN_WIDTH_40) |
  				  BIT(NL80211_CHAN_WIDTH_80) |
  				  BIT(NL80211_CHAN_WIDTH_80P80) |
  				  BIT(NL80211_CHAN_WIDTH_160) |
  				  BIT(NL80211_CHAN_WIDTH_5) |
  				  BIT(NL80211_CHAN_WIDTH_10))))
  			return -EINVAL;
  	}
ad932f046   Arik Nemtsov   cfg80211: leave i...
655
656
657
658
659
660
661
662
663
664
  	/*
  	 * if a wiphy has unsupported modes for regulatory channel enforcement,
  	 * opt-out of enforcement checking
  	 */
  	if (wiphy->interface_modes & ~(BIT(NL80211_IFTYPE_STATION) |
  				       BIT(NL80211_IFTYPE_P2P_CLIENT) |
  				       BIT(NL80211_IFTYPE_AP) |
  				       BIT(NL80211_IFTYPE_P2P_GO) |
  				       BIT(NL80211_IFTYPE_ADHOC) |
  				       BIT(NL80211_IFTYPE_P2P_DEVICE) |
cb3b7d876   Ayala Beker   cfg80211: add sta...
665
  				       BIT(NL80211_IFTYPE_NAN) |
ad932f046   Arik Nemtsov   cfg80211: leave i...
666
667
668
  				       BIT(NL80211_IFTYPE_AP_VLAN) |
  				       BIT(NL80211_IFTYPE_MONITOR)))
  		wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
b0d7aa595   Jonathan Doron   cfg80211: allow w...
669
670
671
672
673
674
675
  	if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
  		    (wiphy->regulatory_flags &
  					(REGULATORY_CUSTOM_REG |
  					 REGULATORY_STRICT_REG |
  					 REGULATORY_COUNTRY_IE_FOLLOW_POWER |
  					 REGULATORY_COUNTRY_IE_IGNORE))))
  		return -EINVAL;
be29b99a9   Amitkumar Karwar   cfg80211/nl80211:...
676
677
678
679
680
681
682
  	if (WARN_ON(wiphy->coalesce &&
  		    (!wiphy->coalesce->n_rules ||
  		     !wiphy->coalesce->n_patterns) &&
  		    (!wiphy->coalesce->pattern_min_len ||
  		     wiphy->coalesce->pattern_min_len >
  			wiphy->coalesce->pattern_max_len)))
  		return -EINVAL;
562a74803   Johannes Berg   nl80211: advertis...
683
684
685
  	if (WARN_ON(wiphy->ap_sme_capa &&
  		    !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
  		return -EINVAL;
ef15aac60   Johannes Berg   cfg80211: export ...
686
687
688
689
690
691
692
693
  	if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
  		return -EINVAL;
  
  	if (WARN_ON(wiphy->addresses &&
  		    !is_zero_ether_addr(wiphy->perm_addr) &&
  		    memcmp(wiphy->perm_addr, wiphy->addresses[0].addr,
  			   ETH_ALEN)))
  		return -EINVAL;
77765eaf5   Vasanthakumar Thiagarajan   cfg80211/nl80211:...
694
695
696
697
  	if (WARN_ON(wiphy->max_acl_mac_addrs &&
  		    (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) ||
  		     !rdev->ops->set_mac_acl)))
  		return -EINVAL;
38de03d2a   Arend van Spriel   nl80211: add feat...
698
699
700
701
702
703
  	/* assure only valid behaviours are flagged by driver
  	 * hence subtract 2 as bit 0 is invalid.
  	 */
  	if (WARN_ON(wiphy->bss_select_support &&
  		    (wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
  		return -EINVAL;
3a00df570   Avraham Stern   cfg80211: support...
704
705
706
707
  	if (WARN_ON(wiphy_ext_feature_isset(&rdev->wiphy,
  					    NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X) &&
  		    (!rdev->ops->set_pmk || !rdev->ops->del_pmk)))
  		return -EINVAL;
7f9a3e150   Vidyullatha Kanchanapally   nl80211: Update E...
708
709
710
  	if (WARN_ON(!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
  		    rdev->ops->update_connect_params))
  		return -EINVAL;
ef15aac60   Johannes Berg   cfg80211: export ...
711
712
  	if (wiphy->addresses)
  		memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
713
714
  	/* sanity check ifmodes */
  	WARN_ON(!ifmodes);
2e161f78e   Johannes Berg   cfg80211/mac80211...
715
  	ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1;
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
716
717
  	if (WARN_ON(ifmodes != wiphy->interface_modes))
  		wiphy->interface_modes = ifmodes;
8318d78a4   Johannes Berg   cfg80211 API for ...
718

7527a782e   Johannes Berg   cfg80211: adverti...
719
720
721
  	res = wiphy_verify_combinations(wiphy);
  	if (res)
  		return res;
8318d78a4   Johannes Berg   cfg80211 API for ...
722
  	/* sanity check supported bands/channels */
57fbcce37   Johannes Berg   cfg80211: remove ...
723
  	for (band = 0; band < NUM_NL80211_BANDS; band++) {
c4cbaf797   Luca Coelho   cfg80211: Add sup...
724
  		u16 types = 0;
f43813652   Johannes Berg   cfg80211: require...
725
  		bool have_he = false;
c4cbaf797   Luca Coelho   cfg80211: Add sup...
726

8318d78a4   Johannes Berg   cfg80211 API for ...
727
728
729
730
731
  		sband = wiphy->bands[band];
  		if (!sband)
  			continue;
  
  		sband->band = band;
3a0c52a6d   Vladimir Kondratiev   cfg80211: add 802...
732
733
734
  		if (WARN_ON(!sband->n_channels))
  			return -EINVAL;
  		/*
df78a0c0b   Thomas Pedersen   nl80211: S1G band...
735
  		 * on 60GHz or sub-1Ghz band, there are no legacy rates, so
3a0c52a6d   Vladimir Kondratiev   cfg80211: add 802...
736
737
  		 * n_bitrates is 0
  		 */
df78a0c0b   Thomas Pedersen   nl80211: S1G band...
738
739
  		if (WARN_ON((band != NL80211_BAND_60GHZ &&
  			     band != NL80211_BAND_S1GHZ) &&
3a0c52a6d   Vladimir Kondratiev   cfg80211: add 802...
740
  			    !sband->n_bitrates))
881d948c2   Johannes Berg   wireless: restric...
741
  			return -EINVAL;
461ce35d5   Johannes Berg   cfg80211: reject ...
742
743
744
745
  		if (WARN_ON(band == NL80211_BAND_6GHZ &&
  			    (sband->ht_cap.ht_supported ||
  			     sband->vht_cap.vht_supported)))
  			return -EINVAL;
881d948c2   Johannes Berg   wireless: restric...
746
  		/*
40db6c77a   Amitkumar Karwar   cfg80211: module_...
747
748
749
750
751
  		 * Since cfg80211_disable_40mhz_24ghz is global, we can
  		 * modify the sband's ht data even if the driver uses a
  		 * global structure for that.
  		 */
  		if (cfg80211_disable_40mhz_24ghz &&
57fbcce37   Johannes Berg   cfg80211: remove ...
752
  		    band == NL80211_BAND_2GHZ &&
40db6c77a   Amitkumar Karwar   cfg80211: module_...
753
754
755
756
757
758
  		    sband->ht_cap.ht_supported) {
  			sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
  			sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
  		}
  
  		/*
881d948c2   Johannes Berg   wireless: restric...
759
760
761
762
763
  		 * Since we use a u32 for rate bitmaps in
  		 * ieee80211_get_response_rate, we cannot
  		 * have more than 32 legacy rates.
  		 */
  		if (WARN_ON(sband->n_bitrates > 32))
8318d78a4   Johannes Berg   cfg80211 API for ...
764
  			return -EINVAL;
8318d78a4   Johannes Berg   cfg80211 API for ...
765
766
767
768
  
  		for (i = 0; i < sband->n_channels; i++) {
  			sband->channels[i].orig_flags =
  				sband->channels[i].flags;
c4a9fafc7   Felix Fietkau   cfg80211: fix ant...
769
  			sband->channels[i].orig_mag = INT_MAX;
8318d78a4   Johannes Berg   cfg80211 API for ...
770
771
772
  			sband->channels[i].orig_mpwr =
  				sband->channels[i].max_power;
  			sband->channels[i].band = band;
be689f68d   Johannes Berg   cfg80211: reject ...
773
774
775
  
  			if (WARN_ON(sband->channels[i].freq_offset >= 1000))
  				return -EINVAL;
8318d78a4   Johannes Berg   cfg80211 API for ...
776
  		}
c4cbaf797   Luca Coelho   cfg80211: Add sup...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
  		for (i = 0; i < sband->n_iftype_data; i++) {
  			const struct ieee80211_sband_iftype_data *iftd;
  
  			iftd = &sband->iftype_data[i];
  
  			if (WARN_ON(!iftd->types_mask))
  				return -EINVAL;
  			if (WARN_ON(types & iftd->types_mask))
  				return -EINVAL;
  
  			/* at least one piece of information must be present */
  			if (WARN_ON(!iftd->he_cap.has_he))
  				return -EINVAL;
  
  			types |= iftd->types_mask;
f43813652   Johannes Berg   cfg80211: require...
792
793
794
795
796
797
  
  			if (i == 0)
  				have_he = iftd->he_cap.has_he;
  			else
  				have_he = have_he &&
  					  iftd->he_cap.has_he;
c4cbaf797   Luca Coelho   cfg80211: Add sup...
798
  		}
f43813652   Johannes Berg   cfg80211: require...
799
800
  		if (WARN_ON(!have_he && band == NL80211_BAND_6GHZ))
  			return -EINVAL;
8318d78a4   Johannes Berg   cfg80211 API for ...
801
802
803
804
805
806
807
  		have_band = true;
  	}
  
  	if (!have_band) {
  		WARN_ON(1);
  		return -EINVAL;
  	}
901bb9891   Johannes Berg   nl80211: require ...
808
809
810
811
812
813
814
815
816
817
818
819
  	for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
  		/*
  		 * Validate we have a policy (can be explicitly set to
  		 * VENDOR_CMD_RAW_DATA which is non-NULL) and also that
  		 * we have at least one of doit/dumpit.
  		 */
  		if (WARN_ON(!rdev->wiphy.vendor_commands[i].policy))
  			return -EINVAL;
  		if (WARN_ON(!rdev->wiphy.vendor_commands[i].doit &&
  			    !rdev->wiphy.vendor_commands[i].dumpit))
  			return -EINVAL;
  	}
dfb89c56a   Johannes Berg   cfg80211: don't a...
820
  #ifdef CONFIG_PM
964dc9e2c   Johannes Berg   cfg80211: take Wo...
821
822
823
824
825
  	if (WARN_ON(rdev->wiphy.wowlan && rdev->wiphy.wowlan->n_patterns &&
  		    (!rdev->wiphy.wowlan->pattern_min_len ||
  		     rdev->wiphy.wowlan->pattern_min_len >
  				rdev->wiphy.wowlan->pattern_max_len)))
  		return -EINVAL;
dfb89c56a   Johannes Berg   cfg80211: don't a...
826
  #endif
ff1b6e69a   Johannes Berg   nl80211/cfg80211:...
827

8318d78a4   Johannes Berg   cfg80211 API for ...
828
829
  	/* check and set up bitrates */
  	ieee80211_set_bitrate_flags(wiphy);
00c3a6ed6   Johannes Berg   cfg80211: don't a...
830
  	rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH;
aa5f66d5a   Johannes Berg   cfg80211: fix sys...
831
  	rtnl_lock();
79c97e97a   Johannes Berg   cfg80211: clean u...
832
  	res = device_add(&rdev->wiphy.dev);
c3d34d5d9   John W. Linville   wireless: registe...
833
  	if (res) {
aa5f66d5a   Johannes Berg   cfg80211: fix sys...
834
  		rtnl_unlock();
c3d34d5d9   John W. Linville   wireless: registe...
835
836
  		return res;
  	}
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
837

2f0accc13   Johannes Berg   cfg80211: fix rfk...
838
  	/* set up regulatory info */
57b5ce072   Luis R. Rodriguez   cfg80211: add cel...
839
  	wiphy_regulatory_register(wiphy);
2f0accc13   Johannes Berg   cfg80211: fix rfk...
840

5f2aa25e0   Johannes Berg   cfg80211: rcu-ify...
841
  	list_add_rcu(&rdev->list, &cfg80211_rdev_list);
f5ea9120b   Johannes Berg   nl80211: add gene...
842
  	cfg80211_rdev_list_generation++;
704232c27   Johannes Berg   [WIRELESS] cfg802...
843
844
  
  	/* add to debugfs */
d82574a8e   Greg Kroah-Hartman   cfg80211: no need...
845
846
  	rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy),
  						    ieee80211_debugfs_dir);
704232c27   Johannes Berg   [WIRELESS] cfg802...
847

a796dac9a   Tomasz Bursztyka   wireless: core: R...
848
849
  	cfg80211_debugfs_rdev_add(rdev);
  	nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
a2f73b6c5   Luis R. Rodriguez   cfg80211: move re...
850
  	if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
73d54c9e7   Luis R. Rodriguez   cfg80211: add reg...
851
852
853
854
855
856
857
858
859
  		struct regulatory_request request;
  
  		request.wiphy_idx = get_wiphy_idx(wiphy);
  		request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
  		request.alpha2[0] = '9';
  		request.alpha2[1] = '9';
  
  		nl80211_send_reg_change_event(&request);
  	}
019ae3a91   Kanchanapally, Vidyullatha   cfg80211: Adverti...
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
  	/* Check that nobody globally advertises any capabilities they do not
  	 * advertise on all possible interface types.
  	 */
  	if (wiphy->extended_capabilities_len &&
  	    wiphy->num_iftype_ext_capab &&
  	    wiphy->iftype_ext_capab) {
  		u8 supported_on_all, j;
  		const struct wiphy_iftype_ext_capab *capab;
  
  		capab = wiphy->iftype_ext_capab;
  		for (j = 0; j < wiphy->extended_capabilities_len; j++) {
  			if (capab[0].extended_capabilities_len > j)
  				supported_on_all =
  					capab[0].extended_capabilities[j];
  			else
  				supported_on_all = 0x00;
  			for (i = 1; i < wiphy->num_iftype_ext_capab; i++) {
  				if (j >= capab[i].extended_capabilities_len) {
  					supported_on_all = 0x00;
  					break;
  				}
  				supported_on_all &=
  					capab[i].extended_capabilities[j];
  			}
  			if (WARN_ON(wiphy->extended_capabilities[j] &
  				    ~supported_on_all))
  				break;
  		}
  	}
ecb443355   Stanislaw Gruszka   mac80211: fix sus...
889
890
  	rdev->wiphy.registered = true;
  	rtnl_unlock();
aa5f66d5a   Johannes Berg   cfg80211: fix sys...
891
892
893
894
895
896
897
898
  
  	res = rfkill_register(rdev->rfkill);
  	if (res) {
  		rfkill_destroy(rdev->rfkill);
  		rdev->rfkill = NULL;
  		wiphy_unregister(&rdev->wiphy);
  		return res;
  	}
2f0accc13   Johannes Berg   cfg80211: fix rfk...
899
  	return 0;
704232c27   Johannes Berg   [WIRELESS] cfg802...
900
901
  }
  EXPORT_SYMBOL(wiphy_register);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
902
903
  void wiphy_rfkill_start_polling(struct wiphy *wiphy)
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
904
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
905

79c97e97a   Johannes Berg   cfg80211: clean u...
906
  	if (!rdev->ops->rfkill_poll)
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
907
  		return;
79c97e97a   Johannes Berg   cfg80211: clean u...
908
909
  	rdev->rfkill_ops.poll = cfg80211_rfkill_poll;
  	rfkill_resume_polling(rdev->rfkill);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
910
911
912
913
914
  }
  EXPORT_SYMBOL(wiphy_rfkill_start_polling);
  
  void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
915
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
916

79c97e97a   Johannes Berg   cfg80211: clean u...
917
  	rfkill_pause_polling(rdev->rfkill);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
918
919
  }
  EXPORT_SYMBOL(wiphy_rfkill_stop_polling);
704232c27   Johannes Berg   [WIRELESS] cfg802...
920
921
  void wiphy_unregister(struct wiphy *wiphy)
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
922
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
704232c27   Johannes Berg   [WIRELESS] cfg802...
923

ad002395f   Johannes Berg   cfg80211: fix dan...
924
925
  	wait_event(rdev->dev_wait, ({
  		int __count;
5fe231e87   Johannes Berg   cfg80211: vastly ...
926
  		rtnl_lock();
ad002395f   Johannes Berg   cfg80211: fix dan...
927
  		__count = rdev->opencount;
5fe231e87   Johannes Berg   cfg80211: vastly ...
928
  		rtnl_unlock();
c4f608462   Cristian Chilipirea   Net: wireless: co...
929
  		__count == 0; }));
ad002395f   Johannes Berg   cfg80211: fix dan...
930

aa5f66d5a   Johannes Berg   cfg80211: fix sys...
931
932
  	if (rdev->rfkill)
  		rfkill_unregister(rdev->rfkill);
256c90ded   Johannes Berg   cfg80211: fix pot...
933

5fe231e87   Johannes Berg   cfg80211: vastly ...
934
  	rtnl_lock();
3bb205567   Johannes Berg   cfg80211: send ev...
935
  	nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
5fe231e87   Johannes Berg   cfg80211: vastly ...
936
  	rdev->wiphy.registered = false;
53873f134   Johannes Berg   cfg80211: make wd...
937
  	WARN_ON(!list_empty(&rdev->wiphy.wdev_list));
ad002395f   Johannes Berg   cfg80211: fix dan...
938
939
940
941
942
  
  	/*
  	 * First remove the hardware from everywhere, this makes
  	 * it impossible to find from userspace.
  	 */
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
943
  	debugfs_remove_recursive(rdev->wiphy.debugfsdir);
5f2aa25e0   Johannes Berg   cfg80211: rcu-ify...
944
945
  	list_del_rcu(&rdev->list);
  	synchronize_rcu();
f16bfc1c0   Johannes Berg   [WIRELESS] cfg802...
946
947
  
  	/*
bfead0808   Luis R. Rodriguez   cfg80211: rename ...
948
949
950
951
  	 * If this device got a regulatory hint tell core its
  	 * free to listen now to a new shiny device regulatory hint
  	 */
  	wiphy_regulatory_deregister(wiphy);
3f2355cb9   Luis R. Rodriguez   cfg80211/mac80211...
952

f5ea9120b   Johannes Berg   nl80211: add gene...
953
  	cfg80211_rdev_list_generation++;
79c97e97a   Johannes Berg   cfg80211: clean u...
954
  	device_del(&rdev->wiphy.dev);
704232c27   Johannes Berg   [WIRELESS] cfg802...
955

5fe231e87   Johannes Berg   cfg80211: vastly ...
956
  	rtnl_unlock();
6682588a0   Johannes Berg   cfg80211: fix unr...
957

36e6fea84   Johannes Berg   cfg80211: check f...
958
  	flush_work(&rdev->scan_done_wk);
6682588a0   Johannes Berg   cfg80211: fix unr...
959
  	cancel_work_sync(&rdev->conn_work);
6682588a0   Johannes Berg   cfg80211: fix unr...
960
  	flush_work(&rdev->event_work);
04f39047a   Simon Wunderlich   nl80211/cfg80211:...
961
  	cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
78f22b6a3   Johannes Berg   cfg80211: allow u...
962
  	flush_work(&rdev->destroy_work);
93a1e86ce   Jukka Rissanen   nl80211: Stop sch...
963
  	flush_work(&rdev->sched_scan_stop_wk);
897667273   Vasanthakumar Thiagarajan   cfg80211: Share C...
964
965
  	flush_work(&rdev->propagate_radar_detect_wk);
  	flush_work(&rdev->propagate_cac_done_wk);
79ea1e12c   Johannes Berg   cfg80211: fix man...
966
  	flush_work(&rdev->mgmt_registrations_update_wk);
6d52563f2   Johannes Berg   cfg80211/mac80211...
967

6abb9cb99   Johannes Berg   cfg80211: make Wo...
968
969
  #ifdef CONFIG_PM
  	if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
e35e4d28b   Hila Gonen   cfg80211: add wra...
970
  		rdev_set_wakeup(rdev, false);
6abb9cb99   Johannes Berg   cfg80211: make Wo...
971
  #endif
6d52563f2   Johannes Berg   cfg80211/mac80211...
972
  	cfg80211_rdev_free_wowlan(rdev);
be29b99a9   Amitkumar Karwar   cfg80211/nl80211:...
973
  	cfg80211_rdev_free_coalesce(rdev);
704232c27   Johannes Berg   [WIRELESS] cfg802...
974
975
  }
  EXPORT_SYMBOL(wiphy_unregister);
79c97e97a   Johannes Berg   cfg80211: clean u...
976
  void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
704232c27   Johannes Berg   [WIRELESS] cfg802...
977
  {
2a5193119   Johannes Berg   cfg80211/nl80211:...
978
  	struct cfg80211_internal_bss *scan, *tmp;
37c73b5f3   Ben Greear   cfg80211: allow r...
979
  	struct cfg80211_beacon_registration *reg, *treg;
79c97e97a   Johannes Berg   cfg80211: clean u...
980
  	rfkill_destroy(rdev->rfkill);
37c73b5f3   Ben Greear   cfg80211: allow r...
981
982
983
984
  	list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
  		list_del(&reg->list);
  		kfree(reg);
  	}
79c97e97a   Johannes Berg   cfg80211: clean u...
985
  	list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
5b112d3d0   Johannes Berg   cfg80211: pass wi...
986
  		cfg80211_put_bss(&rdev->wiphy, &scan->pub);
79c97e97a   Johannes Berg   cfg80211: clean u...
987
  	kfree(rdev);
704232c27   Johannes Berg   [WIRELESS] cfg802...
988
989
990
991
992
993
994
  }
  
  void wiphy_free(struct wiphy *wiphy)
  {
  	put_device(&wiphy->dev);
  }
  EXPORT_SYMBOL(wiphy_free);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
995
996
  void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
997
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
998

79c97e97a   Johannes Berg   cfg80211: clean u...
999
  	if (rfkill_set_hw_state(rdev->rfkill, blocked))
3cfe91c4c   Johannes Berg   cfg80211: always ...
1000
  		schedule_work(&rdev->rfkill_block);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
1001
1002
  }
  EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
4a4b81695   Andrew Zaborowski   cfg80211: Accept ...
1003
1004
1005
1006
1007
  void cfg80211_cqm_config_free(struct wireless_dev *wdev)
  {
  	kfree(wdev->cqm_config);
  	wdev->cqm_config = NULL;
  }
85dd3da43   Johannes Berg   cfg80211: combine...
1008
  static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
98104fded   Johannes Berg   cfg80211: add P2P...
1009
  {
f26cbf401   Zhao, Gang   cfg80211: change ...
1010
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
98104fded   Johannes Berg   cfg80211: add P2P...
1011
1012
  
  	ASSERT_RTNL();
73350424b   Johannes Berg   cfg80211: pmsr: f...
1013
  	flush_work(&wdev->pmsr_free_wk);
7f8ed01ea   Denis Kenzior   cfg80211: always ...
1014
  	nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
98104fded   Johannes Berg   cfg80211: add P2P...
1015
  	list_del_rcu(&wdev->list);
85dd3da43   Johannes Berg   cfg80211: combine...
1016
1017
  	if (sync)
  		synchronize_rcu();
98104fded   Johannes Berg   cfg80211: add P2P...
1018
  	rdev->devlist_generation++;
85dd3da43   Johannes Berg   cfg80211: combine...
1019
  	cfg80211_mlme_purge_registrations(wdev);
98104fded   Johannes Berg   cfg80211: add P2P...
1020
1021
  	switch (wdev->iftype) {
  	case NL80211_IFTYPE_P2P_DEVICE:
f9f475292   Johannes Berg   cfg80211: always ...
1022
  		cfg80211_stop_p2p_device(rdev, wdev);
98104fded   Johannes Berg   cfg80211: add P2P...
1023
  		break;
cb3b7d876   Ayala Beker   cfg80211: add sta...
1024
1025
1026
  	case NL80211_IFTYPE_NAN:
  		cfg80211_stop_nan(rdev, wdev);
  		break;
98104fded   Johannes Berg   cfg80211: add P2P...
1027
  	default:
98104fded   Johannes Berg   cfg80211: add P2P...
1028
1029
  		break;
  	}
4a4b81695   Andrew Zaborowski   cfg80211: Accept ...
1030

85dd3da43   Johannes Berg   cfg80211: combine...
1031
  #ifdef CONFIG_CFG80211_WEXT
453431a54   Waiman Long   mm, treewide: ren...
1032
  	kfree_sensitive(wdev->wext.keys);
56cb31e18   Stefan Bühler   cfg80211: fix dou...
1033
  	wdev->wext.keys = NULL;
85dd3da43   Johannes Berg   cfg80211: combine...
1034
1035
1036
1037
  #endif
  	/* only initialized if we have a netdev */
  	if (wdev->netdev)
  		flush_work(&wdev->disconnect_wk);
4a4b81695   Andrew Zaborowski   cfg80211: Accept ...
1038
  	cfg80211_cqm_config_free(wdev);
98104fded   Johannes Berg   cfg80211: add P2P...
1039
  }
85dd3da43   Johannes Berg   cfg80211: combine...
1040
1041
1042
1043
1044
1045
1046
1047
  
  void cfg80211_unregister_wdev(struct wireless_dev *wdev)
  {
  	if (WARN_ON(wdev->netdev))
  		return;
  
  	__cfg80211_unregister_wdev(wdev, true);
  }
98104fded   Johannes Berg   cfg80211: add P2P...
1048
  EXPORT_SYMBOL(cfg80211_unregister_wdev);
f1e3d556a   Johannes Berg   cfg80211: make de...
1049
  static const struct device_type wiphy_type = {
053a93dd1   Marcel Holtmann   cfg80211: assign ...
1050
1051
  	.name	= "wlan",
  };
dbbae26af   Michal Kazior   cfg80211: track m...
1052
1053
1054
  void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
  			       enum nl80211_iftype iftype, int num)
  {
c5a7e5824   Johannes Berg   cfg80211: fix loc...
1055
  	ASSERT_RTNL();
dbbae26af   Michal Kazior   cfg80211: track m...
1056
1057
1058
1059
  
  	rdev->num_running_ifaces += num;
  	if (iftype == NL80211_IFTYPE_MONITOR)
  		rdev->num_running_monitor_ifaces += num;
dbbae26af   Michal Kazior   cfg80211: track m...
1060
  }
f04c22033   Michal Kazior   cfg80211: export ...
1061
1062
  void __cfg80211_leave(struct cfg80211_registered_device *rdev,
  		      struct wireless_dev *wdev)
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1063
1064
  {
  	struct net_device *dev = wdev->netdev;
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
1065
  	struct cfg80211_sched_scan_request *pos, *tmp;
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1066

24d584d70   Barak Bercovitz   cfg80211: stop sc...
1067
  	ASSERT_RTNL();
f04c22033   Michal Kazior   cfg80211: export ...
1068
  	ASSERT_WDEV_LOCK(wdev);
24d584d70   Barak Bercovitz   cfg80211: stop sc...
1069

9bb7e0f24   Johannes Berg   cfg80211: add pee...
1070
  	cfg80211_pmsr_wdev_down(wdev);
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1071
1072
  	switch (wdev->iftype) {
  	case NL80211_IFTYPE_ADHOC:
f04c22033   Michal Kazior   cfg80211: export ...
1073
  		__cfg80211_leave_ibss(rdev, dev, true);
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1074
1075
1076
  		break;
  	case NL80211_IFTYPE_P2P_CLIENT:
  	case NL80211_IFTYPE_STATION:
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
1077
1078
1079
1080
1081
  		list_for_each_entry_safe(pos, tmp, &rdev->sched_scan_req_list,
  					 list) {
  			if (dev == pos->dev)
  				cfg80211_stop_sched_scan_req(rdev, pos, false);
  		}
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1082

812569699   Stanislaw Gruszka   cfg80211/mac80211...
1083
1084
1085
1086
1087
1088
  #ifdef CONFIG_CFG80211_WEXT
  		kfree(wdev->wext.ie);
  		wdev->wext.ie = NULL;
  		wdev->wext.ie_len = 0;
  		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
  #endif
83739b03d   Johannes Berg   cfg80211: remove ...
1089
1090
  		cfg80211_disconnect(rdev, dev,
  				    WLAN_REASON_DEAUTH_LEAVING, true);
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1091
1092
  		break;
  	case NL80211_IFTYPE_MESH_POINT:
f04c22033   Michal Kazior   cfg80211: export ...
1093
  		__cfg80211_leave_mesh(rdev, dev);
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1094
1095
  		break;
  	case NL80211_IFTYPE_AP:
74418edec   Johannes Berg   cfg80211: fix P2P...
1096
  	case NL80211_IFTYPE_P2P_GO:
f04c22033   Michal Kazior   cfg80211: export ...
1097
  		__cfg80211_stop_ap(rdev, dev, true);
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1098
  		break;
6e0bd6c35   Rostislav Lisovy   cfg80211: 802.11p...
1099
1100
1101
  	case NL80211_IFTYPE_OCB:
  		__cfg80211_leave_ocb(rdev, dev);
  		break;
de4fcbadd   Johannes Berg   cfg80211: avoid u...
1102
1103
1104
1105
  	case NL80211_IFTYPE_WDS:
  		/* must be handled by mac80211/driver, has no APIs */
  		break;
  	case NL80211_IFTYPE_P2P_DEVICE:
cb3b7d876   Ayala Beker   cfg80211: add sta...
1106
  	case NL80211_IFTYPE_NAN:
de4fcbadd   Johannes Berg   cfg80211: avoid u...
1107
1108
1109
1110
1111
1112
1113
1114
1115
  		/* cannot happen, has no netdev */
  		break;
  	case NL80211_IFTYPE_AP_VLAN:
  	case NL80211_IFTYPE_MONITOR:
  		/* nothing to do */
  		break;
  	case NL80211_IFTYPE_UNSPECIFIED:
  	case NUM_NL80211_IFTYPES:
  		/* invalid */
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1116
1117
  		break;
  	}
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1118
  }
f04c22033   Michal Kazior   cfg80211: export ...
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  void cfg80211_leave(struct cfg80211_registered_device *rdev,
  		    struct wireless_dev *wdev)
  {
  	wdev_lock(wdev);
  	__cfg80211_leave(rdev, wdev);
  	wdev_unlock(wdev);
  }
  
  void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
  			 gfp_t gfp)
  {
  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
  	struct cfg80211_event *ev;
  	unsigned long flags;
  
  	trace_cfg80211_stop_iface(wiphy, wdev);
  
  	ev = kzalloc(sizeof(*ev), gfp);
  	if (!ev)
  		return;
  
  	ev->type = EVENT_STOPPED;
  
  	spin_lock_irqsave(&wdev->event_lock, flags);
  	list_add_tail(&ev->list, &wdev->event_list);
  	spin_unlock_irqrestore(&wdev->event_lock, flags);
  	queue_work(cfg80211_wq, &rdev->event_work);
  }
  EXPORT_SYMBOL(cfg80211_stop_iface);
9bdaf3b91   Johannes Berg   cfg80211: initial...
1148
  void cfg80211_init_wdev(struct wireless_dev *wdev)
e4d4216e9   Johannes Berg   cfg80211: combine...
1149
1150
1151
1152
1153
1154
  {
  	mutex_init(&wdev->mtx);
  	INIT_LIST_HEAD(&wdev->event_list);
  	spin_lock_init(&wdev->event_lock);
  	INIT_LIST_HEAD(&wdev->mgmt_registrations);
  	spin_lock_init(&wdev->mgmt_registrations_lock);
9bb7e0f24   Johannes Berg   cfg80211: add pee...
1155
1156
1157
  	INIT_LIST_HEAD(&wdev->pmsr_list);
  	spin_lock_init(&wdev->pmsr_lock);
  	INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
e4d4216e9   Johannes Berg   cfg80211: combine...
1158

9bdaf3b91   Johannes Berg   cfg80211: initial...
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
  #ifdef CONFIG_CFG80211_WEXT
  	wdev->wext.default_key = -1;
  	wdev->wext.default_mgmt_key = -1;
  	wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
  #endif
  
  	if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
  		wdev->ps = true;
  	else
  		wdev->ps = false;
  	/* allow mac80211 to determine the timeout */
  	wdev->ps_timeout = -1;
  
  	if ((wdev->iftype == NL80211_IFTYPE_STATION ||
  	     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
  	     wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
  		wdev->netdev->priv_flags |= IFF_DONT_BRIDGE;
  
  	INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
  }
  
  void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
  			    struct wireless_dev *wdev)
  {
e4d4216e9   Johannes Berg   cfg80211: combine...
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
  	/*
  	 * We get here also when the interface changes network namespaces,
  	 * as it's registered into the new one, but we don't want it to
  	 * change ID in that case. Checking if the ID is already assigned
  	 * works, because 0 isn't considered a valid ID and the memory is
  	 * 0-initialized.
  	 */
  	if (!wdev->identifier)
  		wdev->identifier = ++rdev->wdev_id;
  	list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
  	rdev->devlist_generation++;
ec8f170bc   Johannes Berg   cfg80211: unify s...
1194
1195
  
  	nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
e4d4216e9   Johannes Berg   cfg80211: combine...
1196
  }
c4f608462   Cristian Chilipirea   Net: wireless: co...
1197
  static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
351638e7d   Jiri Pirko   net: pass info st...
1198
  					 unsigned long state, void *ptr)
704232c27   Johannes Berg   [WIRELESS] cfg802...
1199
  {
351638e7d   Jiri Pirko   net: pass info st...
1200
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2a783c136   Johannes Berg   cfg80211: move br...
1201
  	struct wireless_dev *wdev = dev->ieee80211_ptr;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1202
  	struct cfg80211_registered_device *rdev;
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
1203
  	struct cfg80211_sched_scan_request *pos, *tmp;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1204

2a783c136   Johannes Berg   cfg80211: move br...
1205
  	if (!wdev)
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
1206
  		return NOTIFY_DONE;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1207

f26cbf401   Zhao, Gang   cfg80211: change ...
1208
  	rdev = wiphy_to_rdev(wdev->wiphy);
704232c27   Johannes Berg   [WIRELESS] cfg802...
1209

2a783c136   Johannes Berg   cfg80211: move br...
1210
  	WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
60719ffd7   Johannes Berg   cfg80211: show in...
1211

704232c27   Johannes Berg   [WIRELESS] cfg802...
1212
  	switch (state) {
053a93dd1   Marcel Holtmann   cfg80211: assign ...
1213
1214
  	case NETDEV_POST_INIT:
  		SET_NETDEV_DEVTYPE(dev, &wiphy_type);
9bdaf3b91   Johannes Berg   cfg80211: initial...
1215
1216
1217
1218
1219
  		wdev->netdev = dev;
  		/* can only change netns with wiphy */
  		dev->features |= NETIF_F_NETNS_LOCAL;
  
  		cfg80211_init_wdev(wdev);
053a93dd1   Marcel Holtmann   cfg80211: assign ...
1220
  		break;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1221
  	case NETDEV_REGISTER:
0ff6ce7b3   Johannes Berg   cfg80211: fix dea...
1222
1223
1224
1225
1226
  		/*
  		 * NB: cannot take rdev->mtx here because this may be
  		 * called within code protected by it when interfaces
  		 * are added with nl80211.
  		 */
704232c27   Johannes Berg   [WIRELESS] cfg802...
1227
1228
  		if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
  				      "phy80211")) {
e9c0268f0   Joe Perches   net/wireless: Use...
1229
1230
  			pr_err("failed to add phy80211 symlink to netdev!
  ");
704232c27   Johannes Berg   [WIRELESS] cfg802...
1231
  		}
bd2522b16   Andrzej Zaborowski   cfg80211: NL80211...
1232

9bdaf3b91   Johannes Berg   cfg80211: initial...
1233
  		cfg80211_register_wdev(rdev, wdev);
704232c27   Johannes Berg   [WIRELESS] cfg802...
1234
  		break;
04a773ade   Johannes Berg   cfg80211/nl80211:...
1235
  	case NETDEV_GOING_DOWN:
812569699   Stanislaw Gruszka   cfg80211/mac80211...
1236
  		cfg80211_leave(rdev, wdev);
01a0ac417   Johannes Berg   cfg80211: check l...
1237
1238
  		break;
  	case NETDEV_DOWN:
dbbae26af   Michal Kazior   cfg80211: track m...
1239
  		cfg80211_update_iface_num(rdev, wdev->iftype, -1);
a617302c5   Johannes Berg   cfg80211: fix sca...
1240
  		if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
c8cb5b854   Tova Mussai   nl80211/cfg80211:...
1241
1242
1243
  			if (WARN_ON(!rdev->scan_req->notified &&
  				    (!rdev->int_scan_req ||
  				     !rdev->int_scan_req->notified)))
1d76250bd   Avraham Stern   nl80211: support ...
1244
  				rdev->scan_req->info.aborted = true;
f9d15d162   Johannes Berg   cfg80211: send sc...
1245
  			___cfg80211_scan_done(rdev, false);
a617302c5   Johannes Berg   cfg80211: fix sca...
1246
  		}
5fe231e87   Johannes Berg   cfg80211: vastly ...
1247

ca986ad9b   Arend Van Spriel   nl80211: allow mu...
1248
1249
  		list_for_each_entry_safe(pos, tmp,
  					 &rdev->sched_scan_req_list, list) {
d25d062f5   zhong jiang   cfg80211: remove ...
1250
  			if (WARN_ON(pos->dev == wdev->netdev))
ca986ad9b   Arend Van Spriel   nl80211: allow mu...
1251
  				cfg80211_stop_sched_scan_req(rdev, pos, false);
5fe231e87   Johannes Berg   cfg80211: vastly ...
1252
1253
1254
1255
  		}
  
  		rdev->opencount--;
  		wake_up(&rdev->dev_wait);
04a773ade   Johannes Berg   cfg80211/nl80211:...
1256
1257
  		break;
  	case NETDEV_UP:
4290cb4bf   Johannes Berg   cfg80211: reduce ...
1258
  		cfg80211_update_iface_num(rdev, wdev->iftype, 1);
667503ddc   Johannes Berg   cfg80211: fix loc...
1259
  		wdev_lock(wdev);
f21293549   Johannes Berg   cfg80211: managed...
1260
  		switch (wdev->iftype) {
29cbe68c5   Johannes Berg   cfg80211/mac80211...
1261
  #ifdef CONFIG_CFG80211_WEXT
f21293549   Johannes Berg   cfg80211: managed...
1262
  		case NL80211_IFTYPE_ADHOC:
fffd0934b   Johannes Berg   cfg80211: rework ...
1263
  			cfg80211_ibss_wext_join(rdev, wdev);
04a773ade   Johannes Berg   cfg80211/nl80211:...
1264
  			break;
f21293549   Johannes Berg   cfg80211: managed...
1265
  		case NL80211_IFTYPE_STATION:
fffd0934b   Johannes Berg   cfg80211: rework ...
1266
  			cfg80211_mgd_wext_connect(rdev, wdev);
f21293549   Johannes Berg   cfg80211: managed...
1267
  			break;
29cbe68c5   Johannes Berg   cfg80211/mac80211...
1268
  #endif
c80d545da   Javier Cardona   mac80211: Let use...
1269
  #ifdef CONFIG_MAC80211_MESH
29cbe68c5   Johannes Berg   cfg80211/mac80211...
1270
  		case NL80211_IFTYPE_MESH_POINT:
c80d545da   Javier Cardona   mac80211: Let use...
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  			{
  				/* backward compat code... */
  				struct mesh_setup setup;
  				memcpy(&setup, &default_mesh_setup,
  						sizeof(setup));
  				 /* back compat only needed for mesh_id */
  				setup.mesh_id = wdev->ssid;
  				setup.mesh_id_len = wdev->mesh_id_up_len;
  				if (wdev->mesh_id_up_len)
  					__cfg80211_join_mesh(rdev, dev,
  							&setup,
  							&default_mesh_config);
  				break;
  			}
  #endif
f21293549   Johannes Berg   cfg80211: managed...
1286
  		default:
04a773ade   Johannes Berg   cfg80211/nl80211:...
1287
  			break;
f21293549   Johannes Berg   cfg80211: managed...
1288
  		}
667503ddc   Johannes Berg   cfg80211: fix loc...
1289
  		wdev_unlock(wdev);
ad002395f   Johannes Berg   cfg80211: fix dan...
1290
  		rdev->opencount++;
bf6a0579f   Juuso Oikarinen   cfg80211: Fix pow...
1291
1292
1293
1294
1295
  
  		/*
  		 * Configure power management to the driver here so that its
  		 * correctly set also after interface type changes etc.
  		 */
5966f2ddc   Eliad Peller   cfg80211: enter p...
1296
1297
  		if ((wdev->iftype == NL80211_IFTYPE_STATION ||
  		     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
d4f299786   Johannes Berg   cfg80211: combine...
1298
1299
1300
1301
1302
1303
  		    rdev->ops->set_power_mgmt &&
  		    rdev_set_power_mgmt(rdev, dev, wdev->ps,
  					wdev->ps_timeout)) {
  			/* assume this means it's off */
  			wdev->ps = false;
  		}
2a783c136   Johannes Berg   cfg80211: move br...
1304
  		break;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1305
  	case NETDEV_UNREGISTER:
0ff6ce7b3   Johannes Berg   cfg80211: fix dea...
1306
  		/*
e40cbdac0   Johannes Berg   cfg80211: fix NET...
1307
1308
1309
1310
1311
1312
  		 * It is possible to get NETDEV_UNREGISTER
  		 * multiple times. To detect that, check
  		 * that the interface is still on the list
  		 * of registered interfaces, and only then
  		 * remove and clean it up.
  		 */
2a783c136   Johannes Berg   cfg80211: move br...
1313
  		if (!list_empty(&wdev->list)) {
85dd3da43   Johannes Berg   cfg80211: combine...
1314
  			__cfg80211_unregister_wdev(wdev, false);
704232c27   Johannes Berg   [WIRELESS] cfg802...
1315
  			sysfs_remove_link(&dev->dev.kobj, "phy80211");
e40cbdac0   Johannes Berg   cfg80211: fix NET...
1316
  		}
5f2aa25e0   Johannes Berg   cfg80211: rcu-ify...
1317
1318
1319
1320
1321
1322
1323
1324
  		/*
  		 * synchronise (so that we won't find this netdev
  		 * from other code any more) and then clear the list
  		 * head so that the above code can safely check for
  		 * !list_empty() to avoid double-cleanup.
  		 */
  		synchronize_rcu();
  		INIT_LIST_HEAD(&wdev->list);
1f6fc43e6   Daniel Drake   cfg80211: process...
1325
1326
1327
1328
1329
  		/*
  		 * Ensure that all events have been processed and
  		 * freed.
  		 */
  		cfg80211_process_wdev_events(wdev);
f9bef3df5   Ben Greear   wireless: check f...
1330
1331
1332
1333
1334
1335
  
  		if (WARN_ON(wdev->current_bss)) {
  			cfg80211_unhold_bss(wdev->current_bss);
  			cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
  			wdev->current_bss = NULL;
  		}
704232c27   Johannes Berg   [WIRELESS] cfg802...
1336
  		break;
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
1337
  	case NETDEV_PRE_UP:
e6f405112   Manikanta Pubbisetty   {nl,mac}80211: fi...
1338
1339
  		if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype,
  					     wdev->use_4addr, 0))
0b20633d9   Johannes Berg   cfg80211: disallo...
1340
  			return notifier_from_errno(-EOPNOTSUPP);
33d915d9e   Manikanta Pubbisetty   {nl,mac}80211: al...
1341

b6a550156   Luciano Coelho   cfg80211/mac80211...
1342
1343
  		if (rfkill_blocked(rdev->rfkill))
  			return notifier_from_errno(-ERFKILL);
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
1344
  		break;
6784c7db8   Zhao, Gang   cfg80211: change ...
1345
1346
  	default:
  		return NOTIFY_DONE;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1347
  	}
cb150b9d2   Johannes Berg   cfg80211/wext: fi...
1348
  	wireless_nlevent_flush();
6784c7db8   Zhao, Gang   cfg80211: change ...
1349
  	return NOTIFY_OK;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1350
1351
1352
1353
1354
  }
  
  static struct notifier_block cfg80211_netdev_notifier = {
  	.notifier_call = cfg80211_netdev_notifier_call,
  };
463d01832   Johannes Berg   cfg80211: make aw...
1355
1356
1357
1358
1359
  static void __net_exit cfg80211_pernet_exit(struct net *net)
  {
  	struct cfg80211_registered_device *rdev;
  
  	rtnl_lock();
463d01832   Johannes Berg   cfg80211: make aw...
1360
1361
1362
1363
  	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
  		if (net_eq(wiphy_net(&rdev->wiphy), net))
  			WARN_ON(cfg80211_switch_netns(rdev, &init_net));
  	}
463d01832   Johannes Berg   cfg80211: make aw...
1364
1365
1366
1367
1368
1369
1370
1371
  	rtnl_unlock();
  }
  
  static struct pernet_operations cfg80211_pernet_ops = {
  	.exit = cfg80211_pernet_exit,
  };
  
  static int __init cfg80211_init(void)
704232c27   Johannes Berg   [WIRELESS] cfg802...
1372
  {
b2e1b3029   Luis R. Rodriguez   cfg80211: Add new...
1373
  	int err;
463d01832   Johannes Berg   cfg80211: make aw...
1374
1375
1376
  	err = register_pernet_device(&cfg80211_pernet_ops);
  	if (err)
  		goto out_fail_pernet;
b2e1b3029   Luis R. Rodriguez   cfg80211: Add new...
1377
  	err = wiphy_sysfs_init();
704232c27   Johannes Berg   [WIRELESS] cfg802...
1378
1379
1380
1381
1382
1383
  	if (err)
  		goto out_fail_sysfs;
  
  	err = register_netdevice_notifier(&cfg80211_netdev_notifier);
  	if (err)
  		goto out_fail_notifier;
556829657   Johannes Berg   [NL80211]: add ne...
1384
1385
1386
  	err = nl80211_init();
  	if (err)
  		goto out_fail_nl80211;
704232c27   Johannes Berg   [WIRELESS] cfg802...
1387
  	ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
b2e1b3029   Luis R. Rodriguez   cfg80211: Add new...
1388
1389
1390
  	err = regulatory_init();
  	if (err)
  		goto out_fail_reg;
e48190138   Bhaktipriya Shridhar   cfg80211: Remove ...
1391
  	cfg80211_wq = alloc_ordered_workqueue("cfg80211", WQ_MEM_RECLAIM);
f00f188f8   Wei Yongjun   cfg80211: fix err...
1392
1393
  	if (!cfg80211_wq) {
  		err = -ENOMEM;
e60d7443e   Alban Browaeys   wireless : use a ...
1394
  		goto out_fail_wq;
f00f188f8   Wei Yongjun   cfg80211: fix err...
1395
  	}
e60d7443e   Alban Browaeys   wireless : use a ...
1396

704232c27   Johannes Berg   [WIRELESS] cfg802...
1397
  	return 0;
e60d7443e   Alban Browaeys   wireless : use a ...
1398
1399
  out_fail_wq:
  	regulatory_exit();
b2e1b3029   Luis R. Rodriguez   cfg80211: Add new...
1400
1401
  out_fail_reg:
  	debugfs_remove(ieee80211_debugfs_dir);
81daf735f   Junjie Mao   cfg80211: calls n...
1402
  	nl80211_exit();
556829657   Johannes Berg   [NL80211]: add ne...
1403
1404
  out_fail_nl80211:
  	unregister_netdevice_notifier(&cfg80211_netdev_notifier);
704232c27   Johannes Berg   [WIRELESS] cfg802...
1405
1406
1407
  out_fail_notifier:
  	wiphy_sysfs_exit();
  out_fail_sysfs:
463d01832   Johannes Berg   cfg80211: make aw...
1408
1409
  	unregister_pernet_device(&cfg80211_pernet_ops);
  out_fail_pernet:
704232c27   Johannes Berg   [WIRELESS] cfg802...
1410
1411
  	return err;
  }
007f6c5e6   Johannes Berg   cfg80211: support...
1412
  fs_initcall(cfg80211_init);
704232c27   Johannes Berg   [WIRELESS] cfg802...
1413

f884e3879   Uwe Kleine-König   cfg80211: move cf...
1414
  static void __exit cfg80211_exit(void)
704232c27   Johannes Berg   [WIRELESS] cfg802...
1415
1416
  {
  	debugfs_remove(ieee80211_debugfs_dir);
556829657   Johannes Berg   [NL80211]: add ne...
1417
  	nl80211_exit();
704232c27   Johannes Berg   [WIRELESS] cfg802...
1418
1419
  	unregister_netdevice_notifier(&cfg80211_netdev_notifier);
  	wiphy_sysfs_exit();
b2e1b3029   Luis R. Rodriguez   cfg80211: Add new...
1420
  	regulatory_exit();
463d01832   Johannes Berg   cfg80211: make aw...
1421
  	unregister_pernet_device(&cfg80211_pernet_ops);
e60d7443e   Alban Browaeys   wireless : use a ...
1422
  	destroy_workqueue(cfg80211_wq);
704232c27   Johannes Berg   [WIRELESS] cfg802...
1423
1424
  }
  module_exit(cfg80211_exit);