Blame view

net/mac80211/iface.c 26 KB
f0706e828   Jiri Benc   [MAC80211]: Add m...
1
  /*
0d143fe1e   Johannes Berg   mac80211: move re...
2
3
   * Interface handling (except master interface)
   *
f0706e828   Jiri Benc   [MAC80211]: Add m...
4
5
6
   * Copyright 2002-2005, Instant802 Networks, Inc.
   * Copyright 2005-2006, Devicescape Software, Inc.
   * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
75636525f   Johannes Berg   mac80211: revamp ...
7
   * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
f0706e828   Jiri Benc   [MAC80211]: Add m...
8
9
10
11
12
13
14
15
16
17
18
19
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  #include <linux/kernel.h>
  #include <linux/if_arp.h>
  #include <linux/netdevice.h>
  #include <linux/rtnetlink.h>
  #include <net/mac80211.h>
  #include "ieee80211_i.h"
  #include "sta_info.h"
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
20
  #include "debugfs_netdev.h"
ee3858551   Luis Carlos Cobo   mac80211: mesh da...
21
  #include "mesh.h"
0d143fe1e   Johannes Berg   mac80211: move re...
22
  #include "led.h"
244879813   Johannes Berg   mac80211: add dri...
23
  #include "driver-ops.h"
0d143fe1e   Johannes Berg   mac80211: move re...
24

c771c9d8d   Johannes Berg   mac80211: add int...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  /**
   * DOC: Interface list locking
   *
   * The interface list in each struct ieee80211_local is protected
   * three-fold:
   *
   * (1) modifications may only be done under the RTNL
   * (2) modifications and readers are protected against each other by
   *     the iflist_mtx.
   * (3) modifications are done in an RCU manner so atomic readers
   *     can traverse the list in RCU-safe blocks.
   *
   * As a consequence, reads (traversals) of the list can be protected
   * by either the RTNL, the iflist_mtx or RCU.
   */
0d143fe1e   Johannes Berg   mac80211: move re...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
  {
  	int meshhdrlen;
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  
  	meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0;
  
  	/* FIX: what would be proper limits for MTU?
  	 * This interface uses 802.3 frames. */
  	if (new_mtu < 256 ||
  	    new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
  		return -EINVAL;
  	}
  
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
  	printk(KERN_DEBUG "%s: setting MTU %d
  ", dev->name, new_mtu);
  #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
  	dev->mtu = new_mtu;
  	return 0;
  }
  
  static inline int identical_mac_addr_allowed(int type1, int type2)
  {
  	return type1 == NL80211_IFTYPE_MONITOR ||
  		type2 == NL80211_IFTYPE_MONITOR ||
  		(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) ||
  		(type1 == NL80211_IFTYPE_WDS &&
  			(type2 == NL80211_IFTYPE_WDS ||
  			 type2 == NL80211_IFTYPE_AP)) ||
  		(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) ||
  		(type1 == NL80211_IFTYPE_AP_VLAN &&
  			(type2 == NL80211_IFTYPE_AP ||
  			 type2 == NL80211_IFTYPE_AP_VLAN));
  }
  
  static int ieee80211_open(struct net_device *dev)
  {
b4a4bf5d7   Johannes Berg   mac80211: fixups ...
78
79
80
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	struct ieee80211_sub_if_data *nsdata;
  	struct ieee80211_local *local = sdata->local;
0d143fe1e   Johannes Berg   mac80211: move re...
81
82
83
84
  	struct sta_info *sta;
  	struct ieee80211_if_init_conf conf;
  	u32 changed = 0;
  	int res;
e8975581f   Johannes Berg   mac80211: introdu...
85
  	u32 hw_reconf_flags = 0;
0d143fe1e   Johannes Berg   mac80211: move re...
86
  	u8 null_addr[ETH_ALEN] = {0};
0d143fe1e   Johannes Berg   mac80211: move re...
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  	/* fail early if user set an invalid address */
  	if (compare_ether_addr(dev->dev_addr, null_addr) &&
  	    !is_valid_ether_addr(dev->dev_addr))
  		return -EADDRNOTAVAIL;
  
  	/* we hold the RTNL here so can safely walk the list */
  	list_for_each_entry(nsdata, &local->interfaces, list) {
  		struct net_device *ndev = nsdata->dev;
  
  		if (ndev != dev && netif_running(ndev)) {
  			/*
  			 * Allow only a single IBSS interface to be up at any
  			 * time. This is restricted because beacon distribution
  			 * cannot work properly if both are in the same IBSS.
  			 *
  			 * To remove this restriction we'd have to disallow them
  			 * from setting the same SSID on different IBSS interfaces
  			 * belonging to the same hardware. Then, however, we're
  			 * faced with having to adopt two different TSF timers...
  			 */
  			if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
  			    nsdata->vif.type == NL80211_IFTYPE_ADHOC)
  				return -EBUSY;
  
  			/*
  			 * The remaining checks are only performed for interfaces
  			 * with the same MAC address.
  			 */
  			if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
  				continue;
  
  			/*
  			 * check whether it may have the same address
  			 */
  			if (!identical_mac_addr_allowed(sdata->vif.type,
  							nsdata->vif.type))
  				return -ENOTUNIQ;
  
  			/*
  			 * can only add VLANs to enabled APs
  			 */
  			if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
  			    nsdata->vif.type == NL80211_IFTYPE_AP)
  				sdata->bss = &nsdata->u.ap;
  		}
  	}
  
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_WDS:
  		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
  			return -ENOLINK;
  		break;
  	case NL80211_IFTYPE_AP_VLAN:
  		if (!sdata->bss)
  			return -ENOLINK;
  		list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
  		break;
  	case NL80211_IFTYPE_AP:
  		sdata->bss = &sdata->u.ap;
  		break;
  	case NL80211_IFTYPE_MESH_POINT:
  		if (!ieee80211_vif_is_mesh(&sdata->vif))
  			break;
  		/* mesh ifaces must set allmulti to forward mcast traffic */
  		atomic_inc(&local->iff_allmultis);
  		break;
  	case NL80211_IFTYPE_STATION:
  	case NL80211_IFTYPE_MONITOR:
  	case NL80211_IFTYPE_ADHOC:
  		/* no special treatment */
  		break;
  	case NL80211_IFTYPE_UNSPECIFIED:
  	case __NL80211_IFTYPE_AFTER_LAST:
  		/* cannot happen */
  		WARN_ON(1);
  		break;
  	}
  
  	if (local->open_count == 0) {
244879813   Johannes Berg   mac80211: add dri...
166
  		res = drv_start(local);
0d143fe1e   Johannes Berg   mac80211: move re...
167
168
  		if (res)
  			goto err_del_bss;
e8975581f   Johannes Berg   mac80211: introdu...
169
170
  		/* we're brought up, everything changes */
  		hw_reconf_flags = ~0;
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
171
  		ieee80211_led_radio(local, true);
0d143fe1e   Johannes Berg   mac80211: move re...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  	}
  
  	/*
  	 * Check all interfaces and copy the hopefully now-present
  	 * MAC address to those that have the special null one.
  	 */
  	list_for_each_entry(nsdata, &local->interfaces, list) {
  		struct net_device *ndev = nsdata->dev;
  
  		/*
  		 * No need to check netif_running since we do not allow
  		 * it to start up with this invalid address.
  		 */
  		if (compare_ether_addr(null_addr, ndev->dev_addr) == 0)
  			memcpy(ndev->dev_addr,
  			       local->hw.wiphy->perm_addr,
  			       ETH_ALEN);
  	}
  
  	if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0)
  		memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr,
  		       ETH_ALEN);
  
  	/*
  	 * Validate the MAC address for this device.
  	 */
  	if (!is_valid_ether_addr(dev->dev_addr)) {
244879813   Johannes Berg   mac80211: add dri...
199
200
  		if (!local->open_count)
  			drv_stop(local);
0d143fe1e   Johannes Berg   mac80211: move re...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  		return -EADDRNOTAVAIL;
  	}
  
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_AP_VLAN:
  		/* no need to tell driver */
  		break;
  	case NL80211_IFTYPE_MONITOR:
  		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
  			local->cooked_mntrs++;
  			break;
  		}
  
  		/* must be before the call to ieee80211_configure_filter */
  		local->monitors++;
e8975581f   Johannes Berg   mac80211: introdu...
216
  		if (local->monitors == 1) {
0d143fe1e   Johannes Berg   mac80211: move re...
217
  			local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
e8975581f   Johannes Berg   mac80211: introdu...
218
219
  			hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  
  		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
  			local->fif_fcsfail++;
  		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
  			local->fif_plcpfail++;
  		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
  			local->fif_control++;
  		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
  			local->fif_other_bss++;
  
  		netif_addr_lock_bh(local->mdev);
  		ieee80211_configure_filter(local);
  		netif_addr_unlock_bh(local->mdev);
  		break;
  	case NL80211_IFTYPE_STATION:
af8cdcd82   Johannes Berg   mac80211: convert...
235
  		sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
0d143fe1e   Johannes Berg   mac80211: move re...
236
237
238
239
240
  		/* fall through */
  	default:
  		conf.vif = &sdata->vif;
  		conf.type = sdata->vif.type;
  		conf.mac_addr = dev->dev_addr;
244879813   Johannes Berg   mac80211: add dri...
241
  		res = drv_add_interface(local, &conf);
0d143fe1e   Johannes Berg   mac80211: move re...
242
243
  		if (res)
  			goto err_stop;
a3c9aa512   Andrey Yurovsky   mac80211: disable...
244
245
246
247
248
  		if (ieee80211_vif_is_mesh(&sdata->vif)) {
  			local->fif_other_bss++;
  			netif_addr_lock_bh(local->mdev);
  			ieee80211_configure_filter(local);
  			netif_addr_unlock_bh(local->mdev);
0d143fe1e   Johannes Berg   mac80211: move re...
249
  			ieee80211_start_mesh(sdata);
a3c9aa512   Andrey Yurovsky   mac80211: disable...
250
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
251
252
253
  		changed |= ieee80211_reset_erp_info(sdata);
  		ieee80211_bss_info_change_notify(sdata, changed);
  		ieee80211_enable_keys(sdata);
7986cf958   Johannes Berg   mac80211: remove ...
254
  		if (sdata->vif.type == NL80211_IFTYPE_STATION)
0d143fe1e   Johannes Berg   mac80211: move re...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  			netif_carrier_off(dev);
  		else
  			netif_carrier_on(dev);
  	}
  
  	if (sdata->vif.type == NL80211_IFTYPE_WDS) {
  		/* Create STA entry for the WDS peer */
  		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
  				     GFP_KERNEL);
  		if (!sta) {
  			res = -ENOMEM;
  			goto err_del_interface;
  		}
  
  		/* no locking required since STA is not live yet */
  		sta->flags |= WLAN_STA_AUTHORIZED;
  
  		res = sta_info_insert(sta);
  		if (res) {
  			/* STA has been freed */
  			goto err_del_interface;
  		}
  	}
  
  	if (local->open_count == 0) {
  		res = dev_open(local->mdev);
  		WARN_ON(res);
  		if (res)
  			goto err_del_interface;
  		tasklet_enable(&local->tx_pending_tasklet);
  		tasklet_enable(&local->tasklet);
  	}
  
  	/*
  	 * set_multicast_list will be invoked by the networking core
  	 * which will check whether any increments here were done in
  	 * error and sync them down to the hardware as filter flags.
  	 */
  	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
  		atomic_inc(&local->iff_allmultis);
  
  	if (sdata->flags & IEEE80211_SDATA_PROMISC)
  		atomic_inc(&local->iff_promiscs);
5cff20e6c   Johannes Berg   mac80211: tell dr...
298
  	hw_reconf_flags |= __ieee80211_recalc_idle(local);
0d143fe1e   Johannes Berg   mac80211: move re...
299
  	local->open_count++;
e8975581f   Johannes Berg   mac80211: introdu...
300
301
  	if (hw_reconf_flags) {
  		ieee80211_hw_config(local, hw_reconf_flags);
0d143fe1e   Johannes Berg   mac80211: move re...
302
303
304
305
306
307
308
  		/*
  		 * set default queue parameters so drivers don't
  		 * need to initialise the hardware if the hardware
  		 * doesn't start up with sane defaults
  		 */
  		ieee80211_set_wmm_default(sdata);
  	}
10f644a47   Johannes Berg   mac80211: disable...
309
  	ieee80211_recalc_ps(local, -1);
965bedadc   Johannes Berg   mac80211: improve...
310

0d143fe1e   Johannes Berg   mac80211: move re...
311
312
313
314
315
316
  	/*
  	 * ieee80211_sta_work is disabled while network interface
  	 * is down. Therefore, some configuration changes may not
  	 * yet be effective. Trigger execution of ieee80211_sta_work
  	 * to fix this.
  	 */
469002983   Johannes Berg   mac80211: split I...
317
318
  	if (sdata->vif.type == NL80211_IFTYPE_STATION)
  		queue_work(local->hw.workqueue, &sdata->u.mgd.work);
f0706e828   Jiri Benc   [MAC80211]: Add m...
319

0d143fe1e   Johannes Berg   mac80211: move re...
320
321
322
323
  	netif_tx_start_all_queues(dev);
  
  	return 0;
   err_del_interface:
244879813   Johannes Berg   mac80211: add dri...
324
  	drv_remove_interface(local, &conf);
0d143fe1e   Johannes Berg   mac80211: move re...
325
   err_stop:
244879813   Johannes Berg   mac80211: add dri...
326
327
  	if (!local->open_count)
  		drv_stop(local);
0d143fe1e   Johannes Berg   mac80211: move re...
328
329
330
331
332
333
334
335
336
337
338
339
340
   err_del_bss:
  	sdata->bss = NULL;
  	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
  		list_del(&sdata->u.vlan.list);
  	return res;
  }
  
  static int ieee80211_stop(struct net_device *dev)
  {
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	struct ieee80211_local *local = sdata->local;
  	struct ieee80211_if_init_conf conf;
  	struct sta_info *sta;
e8975581f   Johannes Berg   mac80211: introdu...
341
  	u32 hw_reconf_flags = 0;
0d143fe1e   Johannes Berg   mac80211: move re...
342
343
344
345
346
347
348
349
350
351
352
353
354
  
  	/*
  	 * Stop TX on this interface first.
  	 */
  	netif_tx_stop_all_queues(dev);
  
  	/*
  	 * Now delete all active aggregation sessions.
  	 */
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(sta, &local->sta_list, list) {
  		if (sta->sdata == sdata)
2dace10ef   Johannes Berg   mac80211: clean u...
355
  			ieee80211_sta_tear_down_BA_sessions(sta);
0d143fe1e   Johannes Berg   mac80211: move re...
356
357
358
359
360
  	}
  
  	rcu_read_unlock();
  
  	/*
1a28c78b4   Herton Ronaldo Krzesinski   mac80211: deauth ...
361
362
363
364
365
366
367
368
369
370
371
372
  	 * Announce that we are leaving the network, in case we are a
  	 * station interface type. This must be done before removing
  	 * all stations associated with sta_info_flush, otherwise STA
  	 * information will be gone and no announce being done.
  	 */
  	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
  		if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED)
  			ieee80211_sta_deauthenticate(sdata,
  				WLAN_REASON_DEAUTH_LEAVING);
  	}
  
  	/*
0d143fe1e   Johannes Berg   mac80211: move re...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  	 * Remove all stations associated with this interface.
  	 *
  	 * This must be done before calling ops->remove_interface()
  	 * because otherwise we can later invoke ops->sta_notify()
  	 * whenever the STAs are removed, and that invalidates driver
  	 * assumptions about always getting a vif pointer that is valid
  	 * (because if we remove a STA after ops->remove_interface()
  	 * the driver will have removed the vif info already!)
  	 *
  	 * We could relax this and only unlink the stations from the
  	 * hash table and list but keep them on a per-sdata list that
  	 * will be inserted back again when the interface is brought
  	 * up again, but I don't currently see a use case for that,
  	 * except with WDS which gets a STA entry created when it is
  	 * brought up.
  	 */
  	sta_info_flush(local, sdata);
  
  	/*
  	 * Don't count this interface for promisc/allmulti while it
  	 * is down. dev_mc_unsync() will invoke set_multicast_list
  	 * on the master interface which will sync these down to the
  	 * hardware as filter flags.
  	 */
  	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
  		atomic_dec(&local->iff_allmultis);
  
  	if (sdata->flags & IEEE80211_SDATA_PROMISC)
  		atomic_dec(&local->iff_promiscs);
  
  	dev_mc_unsync(local->mdev, dev);
7cbf0ba51   Vivek Natarajan   mac80211: Cancel ...
404
405
  	del_timer_sync(&local->dynamic_ps_timer);
  	cancel_work_sync(&local->dynamic_ps_enable_work);
0d143fe1e   Johannes Berg   mac80211: move re...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  
  	/* APs need special treatment */
  	if (sdata->vif.type == NL80211_IFTYPE_AP) {
  		struct ieee80211_sub_if_data *vlan, *tmp;
  		struct beacon_data *old_beacon = sdata->u.ap.beacon;
  
  		/* remove beacon */
  		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
  		synchronize_rcu();
  		kfree(old_beacon);
  
  		/* down all dependent devices, that is VLANs */
  		list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
  					 u.vlan.list)
  			dev_close(vlan->dev);
  		WARN_ON(!list_empty(&sdata->u.ap.vlans));
  	}
  
  	local->open_count--;
  
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_AP_VLAN:
  		list_del(&sdata->u.vlan.list);
  		/* no need to tell driver */
  		break;
  	case NL80211_IFTYPE_MONITOR:
  		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
  			local->cooked_mntrs--;
  			break;
  		}
  
  		local->monitors--;
e8975581f   Johannes Berg   mac80211: introdu...
438
  		if (local->monitors == 0) {
0d143fe1e   Johannes Berg   mac80211: move re...
439
  			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
e8975581f   Johannes Berg   mac80211: introdu...
440
441
  			hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  
  		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
  			local->fif_fcsfail--;
  		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
  			local->fif_plcpfail--;
  		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
  			local->fif_control--;
  		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
  			local->fif_other_bss--;
  
  		netif_addr_lock_bh(local->mdev);
  		ieee80211_configure_filter(local);
  		netif_addr_unlock_bh(local->mdev);
  		break;
  	case NL80211_IFTYPE_STATION:
469002983   Johannes Berg   mac80211: split I...
457
458
459
  		memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
  		del_timer_sync(&sdata->u.mgd.chswitch_timer);
  		del_timer_sync(&sdata->u.mgd.timer);
0d143fe1e   Johannes Berg   mac80211: move re...
460
461
462
463
464
465
466
  		/*
  		 * If the timer fired while we waited for it, it will have
  		 * requeued the work. Now the work will be running again
  		 * but will not rearm the timer again because it checks
  		 * whether the interface is running, which, at this point,
  		 * it no longer is.
  		 */
469002983   Johannes Berg   mac80211: split I...
467
468
  		cancel_work_sync(&sdata->u.mgd.work);
  		cancel_work_sync(&sdata->u.mgd.chswitch_work);
04de83815   Kalle Valo   mac80211: add bea...
469
470
  
  		cancel_work_sync(&sdata->u.mgd.beacon_loss_work);
0d143fe1e   Johannes Berg   mac80211: move re...
471
472
473
474
475
476
477
  		/*
  		 * When we get here, the interface is marked down.
  		 * Call synchronize_rcu() to wait for the RX path
  		 * should it be using the interface and enqueuing
  		 * frames at this very time on another CPU.
  		 */
  		synchronize_rcu();
469002983   Johannes Berg   mac80211: split I...
478
  		skb_queue_purge(&sdata->u.mgd.skb_queue);
0d143fe1e   Johannes Berg   mac80211: move re...
479

469002983   Johannes Berg   mac80211: split I...
480
  		sdata->u.mgd.flags &= ~(IEEE80211_STA_PRIVACY_INVOKED |
eb46936b9   Vasanthakumar Thiagarajan   mac80211: Scale d...
481
  					IEEE80211_STA_TKIP_WEP_USED);
469002983   Johannes Berg   mac80211: split I...
482
483
484
485
486
487
  		kfree(sdata->u.mgd.extra_ie);
  		sdata->u.mgd.extra_ie = NULL;
  		sdata->u.mgd.extra_ie_len = 0;
  		/* fall through */
  	case NL80211_IFTYPE_ADHOC:
  		if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
469002983   Johannes Berg   mac80211: split I...
488
489
490
491
492
  			del_timer_sync(&sdata->u.ibss.timer);
  			cancel_work_sync(&sdata->u.ibss.work);
  			synchronize_rcu();
  			skb_queue_purge(&sdata->u.ibss.skb_queue);
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
493
494
495
  		/* fall through */
  	case NL80211_IFTYPE_MESH_POINT:
  		if (ieee80211_vif_is_mesh(&sdata->vif)) {
a3c9aa512   Andrey Yurovsky   mac80211: disable...
496
497
498
  			/* other_bss and allmulti are always set on mesh
  			 * ifaces */
  			local->fif_other_bss--;
0d143fe1e   Johannes Berg   mac80211: move re...
499
  			atomic_dec(&local->iff_allmultis);
a3c9aa512   Andrey Yurovsky   mac80211: disable...
500
501
502
503
  
  			netif_addr_lock_bh(local->mdev);
  			ieee80211_configure_filter(local);
  			netif_addr_unlock_bh(local->mdev);
0d143fe1e   Johannes Berg   mac80211: move re...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  			ieee80211_stop_mesh(sdata);
  		}
  		/* fall through */
  	default:
  		if (local->scan_sdata == sdata) {
  			if (!local->ops->hw_scan)
  				cancel_delayed_work_sync(&local->scan_work);
  			/*
  			 * The software scan can no longer run now, so we can
  			 * clear out the scan_sdata reference. However, the
  			 * hardware scan may still be running. The complete
  			 * function must be prepared to handle a NULL value.
  			 */
  			local->scan_sdata = NULL;
  			/*
  			 * The memory barrier guarantees that another CPU
  			 * that is hardware-scanning will now see the fact
  			 * that this interface is gone.
  			 */
  			smp_mb();
  			/*
  			 * If software scanning, complete the scan but since
  			 * the scan_sdata is NULL already don't send out a
  			 * scan event to userspace -- the scan is incomplete.
  			 */
  			if (local->sw_scanning)
2a5193119   Johannes Berg   cfg80211/nl80211:...
530
  				ieee80211_scan_completed(&local->hw, true);
0d143fe1e   Johannes Berg   mac80211: move re...
531
532
533
534
535
536
537
  		}
  
  		conf.vif = &sdata->vif;
  		conf.type = sdata->vif.type;
  		conf.mac_addr = dev->dev_addr;
  		/* disable all keys for as long as this netdev is down */
  		ieee80211_disable_keys(sdata);
244879813   Johannes Berg   mac80211: add dri...
538
  		drv_remove_interface(local, &conf);
0d143fe1e   Johannes Berg   mac80211: move re...
539
540
541
  	}
  
  	sdata->bss = NULL;
5cff20e6c   Johannes Berg   mac80211: tell dr...
542
543
544
  	hw_reconf_flags |= __ieee80211_recalc_idle(local);
  
  	ieee80211_recalc_ps(local, -1);
0d143fe1e   Johannes Berg   mac80211: move re...
545
546
547
  	if (local->open_count == 0) {
  		if (netif_running(local->mdev))
  			dev_close(local->mdev);
244879813   Johannes Berg   mac80211: add dri...
548
  		drv_stop(local);
0d143fe1e   Johannes Berg   mac80211: move re...
549

1f87f7d3a   Johannes Berg   cfg80211: add rfk...
550
  		ieee80211_led_radio(local, false);
0d143fe1e   Johannes Berg   mac80211: move re...
551
552
553
554
555
  
  		flush_workqueue(local->hw.workqueue);
  
  		tasklet_disable(&local->tx_pending_tasklet);
  		tasklet_disable(&local->tasklet);
e8975581f   Johannes Berg   mac80211: introdu...
556
557
558
  
  		/* no reconfiguring after stop! */
  		hw_reconf_flags = 0;
0d143fe1e   Johannes Berg   mac80211: move re...
559
  	}
e8975581f   Johannes Berg   mac80211: introdu...
560
561
562
  	/* do after stop to avoid reconfiguring when we stop anyway */
  	if (hw_reconf_flags)
  		ieee80211_hw_config(local, hw_reconf_flags);
0d143fe1e   Johannes Berg   mac80211: move re...
563
564
565
566
567
  	return 0;
  }
  
  static void ieee80211_set_multicast_list(struct net_device *dev)
  {
0d143fe1e   Johannes Berg   mac80211: move re...
568
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
b4a4bf5d7   Johannes Berg   mac80211: fixups ...
569
  	struct ieee80211_local *local = sdata->local;
0d143fe1e   Johannes Berg   mac80211: move re...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  	int allmulti, promisc, sdata_allmulti, sdata_promisc;
  
  	allmulti = !!(dev->flags & IFF_ALLMULTI);
  	promisc = !!(dev->flags & IFF_PROMISC);
  	sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
  	sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
  
  	if (allmulti != sdata_allmulti) {
  		if (dev->flags & IFF_ALLMULTI)
  			atomic_inc(&local->iff_allmultis);
  		else
  			atomic_dec(&local->iff_allmultis);
  		sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
  	}
  
  	if (promisc != sdata_promisc) {
  		if (dev->flags & IFF_PROMISC)
  			atomic_inc(&local->iff_promiscs);
  		else
  			atomic_dec(&local->iff_promiscs);
  		sdata->flags ^= IEEE80211_SDATA_PROMISC;
  	}
  
  	dev_mc_sync(local->mdev, dev);
  }
75636525f   Johannes Berg   mac80211: revamp ...
595
596
597
598
599
  /*
   * Called when the netdev is removed or, by the code below, before
   * the interface type changes.
   */
  static void ieee80211_teardown_sdata(struct net_device *dev)
f0706e828   Jiri Benc   [MAC80211]: Add m...
600
  {
75636525f   Johannes Berg   mac80211: revamp ...
601
602
603
604
605
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	struct ieee80211_local *local = sdata->local;
  	struct beacon_data *beacon;
  	struct sk_buff *skb;
  	int flushed;
f0706e828   Jiri Benc   [MAC80211]: Add m...
606
  	int i;
75636525f   Johannes Berg   mac80211: revamp ...
607
608
  	/* free extra data */
  	ieee80211_free_keys(sdata);
aee14ceb5   Jouni Malinen   mac80211: Reorder...
609
  	ieee80211_debugfs_remove_netdev(sdata);
f0706e828   Jiri Benc   [MAC80211]: Add m...
610
  	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
75636525f   Johannes Berg   mac80211: revamp ...
611
612
  		__skb_queue_purge(&sdata->fragments[i].skb_list);
  	sdata->fragment_next = 0;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
613

75636525f   Johannes Berg   mac80211: revamp ...
614
  	switch (sdata->vif.type) {
05c914fe3   Johannes Berg   mac80211: use nl8...
615
  	case NL80211_IFTYPE_AP:
75636525f   Johannes Berg   mac80211: revamp ...
616
617
618
619
  		beacon = sdata->u.ap.beacon;
  		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
  		synchronize_rcu();
  		kfree(beacon);
3e122be08   Johannes Berg   mac80211: make ma...
620

75636525f   Johannes Berg   mac80211: revamp ...
621
622
623
624
625
626
  		while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
  			local->total_ps_buffered--;
  			dev_kfree_skb(skb);
  		}
  
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
627
  	case NL80211_IFTYPE_MESH_POINT:
75636525f   Johannes Berg   mac80211: revamp ...
628
  		if (ieee80211_vif_is_mesh(&sdata->vif))
f698d856f   Jasper Bryant-Greene   replace net_devic...
629
  			mesh_rmc_free(sdata);
472dbc45d   Johannes Berg   mac80211: split o...
630
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
631
  	case NL80211_IFTYPE_ADHOC:
af8cdcd82   Johannes Berg   mac80211: convert...
632
633
  		if (WARN_ON(sdata->u.ibss.presp))
  			kfree_skb(sdata->u.ibss.presp);
469002983   Johannes Berg   mac80211: split I...
634
635
636
637
638
  		break;
  	case NL80211_IFTYPE_STATION:
  		kfree(sdata->u.mgd.extra_ie);
  		kfree(sdata->u.mgd.assocreq_ies);
  		kfree(sdata->u.mgd.assocresp_ies);
d7873cb9a   Jouni Malinen   mac80211: Fix mem...
639
  		kfree(sdata->u.mgd.sme_auth_ie);
75636525f   Johannes Berg   mac80211: revamp ...
640
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
641
642
643
  	case NL80211_IFTYPE_WDS:
  	case NL80211_IFTYPE_AP_VLAN:
  	case NL80211_IFTYPE_MONITOR:
75636525f   Johannes Berg   mac80211: revamp ...
644
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
645
646
  	case NL80211_IFTYPE_UNSPECIFIED:
  	case __NL80211_IFTYPE_AFTER_LAST:
75636525f   Johannes Berg   mac80211: revamp ...
647
648
649
650
651
652
  		BUG();
  		break;
  	}
  
  	flushed = sta_info_flush(local, sdata);
  	WARN_ON(flushed);
f0706e828   Jiri Benc   [MAC80211]: Add m...
653
  }
587e729ec   Johannes Berg   mac80211: convert...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
  static const struct net_device_ops ieee80211_dataif_ops = {
  	.ndo_open		= ieee80211_open,
  	.ndo_stop		= ieee80211_stop,
  	.ndo_uninit		= ieee80211_teardown_sdata,
  	.ndo_start_xmit		= ieee80211_subif_start_xmit,
  	.ndo_set_multicast_list = ieee80211_set_multicast_list,
  	.ndo_change_mtu 	= ieee80211_change_mtu,
  	.ndo_set_mac_address 	= eth_mac_addr,
  };
  
  static const struct net_device_ops ieee80211_monitorif_ops = {
  	.ndo_open		= ieee80211_open,
  	.ndo_stop		= ieee80211_stop,
  	.ndo_uninit		= ieee80211_teardown_sdata,
  	.ndo_start_xmit		= ieee80211_monitor_start_xmit,
  	.ndo_set_multicast_list = ieee80211_set_multicast_list,
  	.ndo_change_mtu 	= ieee80211_change_mtu,
  	.ndo_set_mac_address 	= eth_mac_addr,
  };
  
  static void ieee80211_if_setup(struct net_device *dev)
  {
  	ether_setup(dev);
  	dev->netdev_ops = &ieee80211_dataif_ops;
  	dev->wireless_handlers = &ieee80211_iw_handler_def;
  	dev->destructor = free_netdev;
  }
75636525f   Johannes Berg   mac80211: revamp ...
681
682
683
684
  /*
   * Helper function to initialise an interface to a specific type.
   */
  static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
05c914fe3   Johannes Berg   mac80211: use nl8...
685
  				  enum nl80211_iftype type)
f0706e828   Jiri Benc   [MAC80211]: Add m...
686
  {
75636525f   Johannes Berg   mac80211: revamp ...
687
688
689
690
691
  	/* clear type-dependent union */
  	memset(&sdata->u, 0, sizeof(sdata->u));
  
  	/* and set some type-dependent values */
  	sdata->vif.type = type;
587e729ec   Johannes Berg   mac80211: convert...
692
  	sdata->dev->netdev_ops = &ieee80211_dataif_ops;
60719ffd7   Johannes Berg   cfg80211: show in...
693
  	sdata->wdev.iftype = type;
75636525f   Johannes Berg   mac80211: revamp ...
694
695
696
697
698
  
  	/* only monitor differs */
  	sdata->dev->type = ARPHRD_ETHER;
  
  	switch (type) {
05c914fe3   Johannes Berg   mac80211: use nl8...
699
  	case NL80211_IFTYPE_AP:
75636525f   Johannes Berg   mac80211: revamp ...
700
701
702
  		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
  		INIT_LIST_HEAD(&sdata->u.ap.vlans);
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
703
  	case NL80211_IFTYPE_STATION:
9c6bd7901   Johannes Berg   mac80211: reorder...
704
  		ieee80211_sta_setup_sdata(sdata);
472dbc45d   Johannes Berg   mac80211: split o...
705
  		break;
469002983   Johannes Berg   mac80211: split I...
706
707
708
  	case NL80211_IFTYPE_ADHOC:
  		ieee80211_ibss_setup_sdata(sdata);
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
709
  	case NL80211_IFTYPE_MESH_POINT:
75636525f   Johannes Berg   mac80211: revamp ...
710
711
712
  		if (ieee80211_vif_is_mesh(&sdata->vif))
  			ieee80211_mesh_init_sdata(sdata);
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
713
  	case NL80211_IFTYPE_MONITOR:
75636525f   Johannes Berg   mac80211: revamp ...
714
  		sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
587e729ec   Johannes Berg   mac80211: convert...
715
  		sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
75636525f   Johannes Berg   mac80211: revamp ...
716
717
718
  		sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
  				      MONITOR_FLAG_OTHER_BSS;
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
719
720
  	case NL80211_IFTYPE_WDS:
  	case NL80211_IFTYPE_AP_VLAN:
75636525f   Johannes Berg   mac80211: revamp ...
721
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
722
723
  	case NL80211_IFTYPE_UNSPECIFIED:
  	case __NL80211_IFTYPE_AFTER_LAST:
75636525f   Johannes Berg   mac80211: revamp ...
724
725
726
727
728
729
  		BUG();
  		break;
  	}
  
  	ieee80211_debugfs_add_netdev(sdata);
  }
f3947e2df   Johannes Berg   mac80211: push in...
730
  int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
05c914fe3   Johannes Berg   mac80211: use nl8...
731
  			     enum nl80211_iftype type)
75636525f   Johannes Berg   mac80211: revamp ...
732
  {
f3947e2df   Johannes Berg   mac80211: push in...
733
734
735
736
  	ASSERT_RTNL();
  
  	if (type == sdata->vif.type)
  		return 0;
e60c7744f   Johannes Berg   cfg80211: handle ...
737
  	/* Setting ad-hoc mode on non-IBSS channel is not supported. */
dcebf45cd   Pavel Roskin   mac80211: allow m...
738
739
  	if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS &&
  	    type == NL80211_IFTYPE_ADHOC)
e60c7744f   Johannes Berg   cfg80211: handle ...
740
  		return -EOPNOTSUPP;
f3947e2df   Johannes Berg   mac80211: push in...
741
742
743
744
745
746
747
748
  	/*
  	 * We could, here, on changes between IBSS/STA/MESH modes,
  	 * invoke an MLME function instead that disassociates etc.
  	 * and goes into the requested mode.
  	 */
  
  	if (netif_running(sdata->dev))
  		return -EBUSY;
75636525f   Johannes Berg   mac80211: revamp ...
749
750
751
752
753
  	/* Purge and reset type-dependent state. */
  	ieee80211_teardown_sdata(sdata->dev);
  	ieee80211_setup_sdata(sdata, type);
  
  	/* reset some values that shouldn't be kept across type changes */
bda3933a8   Johannes Berg   mac80211: move bs...
754
  	sdata->vif.bss_conf.basic_rates =
96dd22ac0   Johannes Berg   mac80211: inform ...
755
756
  		ieee80211_mandatory_rates(sdata->local,
  			sdata->local->hw.conf.channel->band);
75636525f   Johannes Berg   mac80211: revamp ...
757
  	sdata->drop_unencrypted = 0;
f3947e2df   Johannes Berg   mac80211: push in...
758
759
  
  	return 0;
f0706e828   Jiri Benc   [MAC80211]: Add m...
760
  }
3e122be08   Johannes Berg   mac80211: make ma...
761
  int ieee80211_if_add(struct ieee80211_local *local, const char *name,
05c914fe3   Johannes Berg   mac80211: use nl8...
762
  		     struct net_device **new_dev, enum nl80211_iftype type,
ee3858551   Luis Carlos Cobo   mac80211: mesh da...
763
  		     struct vif_params *params)
f0706e828   Jiri Benc   [MAC80211]: Add m...
764
765
  {
  	struct net_device *ndev;
f0706e828   Jiri Benc   [MAC80211]: Add m...
766
  	struct ieee80211_sub_if_data *sdata = NULL;
75636525f   Johannes Berg   mac80211: revamp ...
767
  	int ret, i;
f0706e828   Jiri Benc   [MAC80211]: Add m...
768
769
  
  	ASSERT_RTNL();
75636525f   Johannes Berg   mac80211: revamp ...
770

32bfd35d4   Johannes Berg   mac80211: dont us...
771
  	ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
f0706e828   Jiri Benc   [MAC80211]: Add m...
772
773
774
  			    name, ieee80211_if_setup);
  	if (!ndev)
  		return -ENOMEM;
f3994ecee   Johannes Berg   mac80211: assign ...
775
776
777
778
779
780
781
782
  	ndev->needed_headroom = local->tx_headroom +
  				4*6 /* four MAC addresses */
  				+ 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
  				+ 6 /* mesh */
  				+ 8 /* rfc1042/bridge tunnel */
  				- ETH_HLEN /* ethernet hard_header_len */
  				+ IEEE80211_ENCRYPT_HEADROOM;
  	ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
f0706e828   Jiri Benc   [MAC80211]: Add m...
783
784
785
786
787
  	ret = dev_alloc_name(ndev, ndev->name);
  	if (ret < 0)
  		goto fail;
  
  	memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
f0706e828   Jiri Benc   [MAC80211]: Add m...
788
  	SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
076ae609d   Johannes Berg   mac80211: disallo...
789
  	ndev->features |= NETIF_F_NETNS_LOCAL;
f0706e828   Jiri Benc   [MAC80211]: Add m...
790

3e122be08   Johannes Berg   mac80211: make ma...
791
792
  	/* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
  	sdata = netdev_priv(ndev);
f0706e828   Jiri Benc   [MAC80211]: Add m...
793
  	ndev->ieee80211_ptr = &sdata->wdev;
75636525f   Johannes Berg   mac80211: revamp ...
794
795
  
  	/* initialise type-independent data */
f0706e828   Jiri Benc   [MAC80211]: Add m...
796
  	sdata->wdev.wiphy = local->hw.wiphy;
f0706e828   Jiri Benc   [MAC80211]: Add m...
797
  	sdata->local = local;
75636525f   Johannes Berg   mac80211: revamp ...
798
799
800
801
802
803
804
805
806
807
808
809
  	sdata->dev = ndev;
  
  	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
  		skb_queue_head_init(&sdata->fragments[i].skb_list);
  
  	INIT_LIST_HEAD(&sdata->key_list);
  
  	sdata->force_unicast_rateidx = -1;
  	sdata->max_ratectrl_rateidx = -1;
  
  	/* setup type-dependent data */
  	ieee80211_setup_sdata(sdata, type);
f0706e828   Jiri Benc   [MAC80211]: Add m...
810
811
812
813
  
  	ret = register_netdevice(ndev);
  	if (ret)
  		goto fail;
902acc789   Johannes Berg   mac80211: clean u...
814
815
  	if (ieee80211_vif_is_mesh(&sdata->vif) &&
  	    params && params->mesh_id_len)
472dbc45d   Johannes Berg   mac80211: split o...
816
817
818
  		ieee80211_sdata_set_mesh_id(sdata,
  					    params->mesh_id_len,
  					    params->mesh_id);
ee3858551   Luis Carlos Cobo   mac80211: mesh da...
819

c771c9d8d   Johannes Berg   mac80211: add int...
820
  	mutex_lock(&local->iflist_mtx);
79010420c   Johannes Berg   [PATCH] mac80211:...
821
  	list_add_tail_rcu(&sdata->list, &local->interfaces);
c771c9d8d   Johannes Berg   mac80211: add int...
822
  	mutex_unlock(&local->iflist_mtx);
79010420c   Johannes Berg   [PATCH] mac80211:...
823

f0706e828   Jiri Benc   [MAC80211]: Add m...
824
825
  	if (new_dev)
  		*new_dev = ndev;
f0706e828   Jiri Benc   [MAC80211]: Add m...
826

f0706e828   Jiri Benc   [MAC80211]: Add m...
827
  	return 0;
75636525f   Johannes Berg   mac80211: revamp ...
828
   fail:
f0706e828   Jiri Benc   [MAC80211]: Add m...
829
830
831
  	free_netdev(ndev);
  	return ret;
  }
f698d856f   Jasper Bryant-Greene   replace net_devic...
832
  void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
f0706e828   Jiri Benc   [MAC80211]: Add m...
833
  {
f0706e828   Jiri Benc   [MAC80211]: Add m...
834
  	ASSERT_RTNL();
11a843b7e   Johannes Berg   [MAC80211]: rewor...
835

c771c9d8d   Johannes Berg   mac80211: add int...
836
  	mutex_lock(&sdata->local->iflist_mtx);
75636525f   Johannes Berg   mac80211: revamp ...
837
  	list_del_rcu(&sdata->list);
c771c9d8d   Johannes Berg   mac80211: add int...
838
  	mutex_unlock(&sdata->local->iflist_mtx);
75636525f   Johannes Berg   mac80211: revamp ...
839
  	synchronize_rcu();
f698d856f   Jasper Bryant-Greene   replace net_devic...
840
  	unregister_netdevice(sdata->dev);
f0706e828   Jiri Benc   [MAC80211]: Add m...
841
  }
75636525f   Johannes Berg   mac80211: revamp ...
842
843
844
845
846
  /*
   * Remove all interfaces, may only be called at hardware unregistration
   * time because it doesn't do RCU-safe list removals.
   */
  void ieee80211_remove_interfaces(struct ieee80211_local *local)
f0706e828   Jiri Benc   [MAC80211]: Add m...
847
  {
75636525f   Johannes Berg   mac80211: revamp ...
848
  	struct ieee80211_sub_if_data *sdata, *tmp;
f0706e828   Jiri Benc   [MAC80211]: Add m...
849
850
  
  	ASSERT_RTNL();
75636525f   Johannes Berg   mac80211: revamp ...
851
  	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
c771c9d8d   Johannes Berg   mac80211: add int...
852
853
854
855
856
857
858
  		/*
  		 * we cannot hold the iflist_mtx across unregister_netdevice,
  		 * but we only need to hold it for list modifications to lock
  		 * out readers since we're under the RTNL here as all other
  		 * writers.
  		 */
  		mutex_lock(&local->iflist_mtx);
75636525f   Johannes Berg   mac80211: revamp ...
859
  		list_del(&sdata->list);
c771c9d8d   Johannes Berg   mac80211: add int...
860
  		mutex_unlock(&local->iflist_mtx);
75636525f   Johannes Berg   mac80211: revamp ...
861
  		unregister_netdevice(sdata->dev);
f0706e828   Jiri Benc   [MAC80211]: Add m...
862
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
863
  }
5cff20e6c   Johannes Berg   mac80211: tell dr...
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
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  
  static u32 ieee80211_idle_off(struct ieee80211_local *local,
  			      const char *reason)
  {
  	if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
  		return 0;
  
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
  	printk(KERN_DEBUG "%s: device no longer idle - %s
  ",
  	       wiphy_name(local->hw.wiphy), reason);
  #endif
  
  	local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
  	return IEEE80211_CONF_CHANGE_IDLE;
  }
  
  static u32 ieee80211_idle_on(struct ieee80211_local *local)
  {
  	if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
  		return 0;
  
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
  	printk(KERN_DEBUG "%s: device now idle
  ",
  	       wiphy_name(local->hw.wiphy));
  #endif
  
  	local->hw.conf.flags |= IEEE80211_CONF_IDLE;
  	return IEEE80211_CONF_CHANGE_IDLE;
  }
  
  u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
  {
  	struct ieee80211_sub_if_data *sdata;
  	int count = 0;
  
  	if (local->hw_scanning || local->sw_scanning)
  		return ieee80211_idle_off(local, "scanning");
  
  	list_for_each_entry(sdata, &local->interfaces, list) {
  		if (!netif_running(sdata->dev))
  			continue;
  		/* do not count disabled managed interfaces */
  		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
  		    sdata->u.mgd.state == IEEE80211_STA_MLME_DISABLED)
  			continue;
  		/* do not count unused IBSS interfaces */
  		if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
  		    !sdata->u.ibss.ssid_len)
  			continue;
  		/* count everything else */
  		count++;
  	}
  
  	if (!count)
  		return ieee80211_idle_on(local);
  	else
  		return ieee80211_idle_off(local, "in use");
  
  	return 0;
  }
  
  void ieee80211_recalc_idle(struct ieee80211_local *local)
  {
  	u32 chg;
  
  	mutex_lock(&local->iflist_mtx);
  	chg = __ieee80211_recalc_idle(local);
  	mutex_unlock(&local->iflist_mtx);
58905ca5b   Johannes Berg   mac80211: fix sca...
934
935
  	if (chg)
  		ieee80211_hw_config(local, chg);
5cff20e6c   Johannes Berg   mac80211: tell dr...
936
  }