Blame view

net/mac80211/iface.c 36 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
   *
   * 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.
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
14
15
16
17
18
  #include <linux/kernel.h>
  #include <linux/if_arp.h>
  #include <linux/netdevice.h>
  #include <linux/rtnetlink.h>
  #include <net/mac80211.h>
cf0277e71   Johannes Berg   mac80211: fix skb...
19
  #include <net/ieee80211_radiotap.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
20
21
  #include "ieee80211_i.h"
  #include "sta_info.h"
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
22
  #include "debugfs_netdev.h"
ee3858551   Luis Carlos Cobo   mac80211: mesh da...
23
  #include "mesh.h"
0d143fe1e   Johannes Berg   mac80211: move re...
24
  #include "led.h"
244879813   Johannes Berg   mac80211: add dri...
25
  #include "driver-ops.h"
cf0277e71   Johannes Berg   mac80211: fix skb...
26
  #include "wme.h"
1be7fe8de   Bill Jordan   mac80211: fix for...
27
  #include "rate.h"
0d143fe1e   Johannes Berg   mac80211: move re...
28

c771c9d8d   Johannes Berg   mac80211: add int...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  /**
   * 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...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  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;
  }
47846c9b0   Johannes Berg   mac80211: reduce ...
65
66
67
  static int ieee80211_change_mac(struct net_device *dev, void *addr)
  {
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
fc5f75773   Kalle Valo   mac80211: fix iee...
68
  	struct sockaddr *sa = addr;
47846c9b0   Johannes Berg   mac80211: reduce ...
69
  	int ret;
9607e6b66   Johannes Berg   mac80211: add iee...
70
  	if (ieee80211_sdata_running(sdata))
47846c9b0   Johannes Berg   mac80211: reduce ...
71
  		return -EBUSY;
fc5f75773   Kalle Valo   mac80211: fix iee...
72
  	ret = eth_mac_addr(dev, sa);
47846c9b0   Johannes Berg   mac80211: reduce ...
73
74
  
  	if (ret == 0)
fc5f75773   Kalle Valo   mac80211: fix iee...
75
  		memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
47846c9b0   Johannes Berg   mac80211: reduce ...
76
77
78
  
  	return ret;
  }
0d143fe1e   Johannes Berg   mac80211: move re...
79
80
81
82
83
84
85
86
87
88
89
90
91
  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));
  }
87490f6db   Johannes Berg   mac80211: split o...
92
93
  static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
  					    enum nl80211_iftype iftype)
0d143fe1e   Johannes Berg   mac80211: move re...
94
  {
b4a4bf5d7   Johannes Berg   mac80211: fixups ...
95
  	struct ieee80211_local *local = sdata->local;
87490f6db   Johannes Berg   mac80211: split o...
96
97
  	struct ieee80211_sub_if_data *nsdata;
  	struct net_device *dev = sdata->dev;
0d143fe1e   Johannes Berg   mac80211: move re...
98

87490f6db   Johannes Berg   mac80211: split o...
99
  	ASSERT_RTNL();
0d143fe1e   Johannes Berg   mac80211: move re...
100
101
102
103
  
  	/* 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;
9607e6b66   Johannes Berg   mac80211: add iee...
104
  		if (ndev != dev && ieee80211_sdata_running(nsdata)) {
0d143fe1e   Johannes Berg   mac80211: move re...
105
106
107
108
109
110
111
112
113
114
  			/*
  			 * 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...
  			 */
87490f6db   Johannes Berg   mac80211: split o...
115
  			if (iftype == NL80211_IFTYPE_ADHOC &&
0d143fe1e   Johannes Berg   mac80211: move re...
116
117
118
119
120
121
122
123
124
125
126
127
128
  			    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
  			 */
87490f6db   Johannes Berg   mac80211: split o...
129
  			if (!identical_mac_addr_allowed(iftype,
0d143fe1e   Johannes Berg   mac80211: move re...
130
131
132
133
134
135
  							nsdata->vif.type))
  				return -ENOTUNIQ;
  
  			/*
  			 * can only add VLANs to enabled APs
  			 */
87490f6db   Johannes Berg   mac80211: split o...
136
  			if (iftype == NL80211_IFTYPE_AP_VLAN &&
0d143fe1e   Johannes Berg   mac80211: move re...
137
138
139
140
  			    nsdata->vif.type == NL80211_IFTYPE_AP)
  				sdata->bss = &nsdata->u.ap;
  		}
  	}
87490f6db   Johannes Berg   mac80211: split o...
141
142
  	return 0;
  }
85416a4fa   Christian Lamparter   mac80211: fix rx ...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
  				    const int offset)
  {
  	struct ieee80211_local *local = sdata->local;
  	u32 flags = sdata->u.mntr_flags;
  
  #define ADJUST(_f, _s)	do {					\
  	if (flags & MONITOR_FLAG_##_f)				\
  		local->fif_##_s += offset;			\
  	} while (0)
  
  	ADJUST(FCSFAIL, fcsfail);
  	ADJUST(PLCPFAIL, plcpfail);
  	ADJUST(CONTROL, control);
  	ADJUST(CONTROL, pspoll);
  	ADJUST(OTHER_BSS, other_bss);
  
  #undef ADJUST
  }
34d4bc4d4   Johannes Berg   mac80211: support...
162
163
164
165
166
167
  /*
   * NOTE: Be very careful when changing this function, it must NOT return
   * an error on interface type changes that have been pre-checked, so most
   * checks should be in ieee80211_check_concurrent_iface.
   */
  static int ieee80211_do_open(struct net_device *dev, bool coming_up)
87490f6db   Johannes Berg   mac80211: split o...
168
169
170
171
172
173
174
  {
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	struct ieee80211_local *local = sdata->local;
  	struct sta_info *sta;
  	u32 changed = 0;
  	int res;
  	u32 hw_reconf_flags = 0;
0d143fe1e   Johannes Berg   mac80211: move re...
175
176
177
178
179
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_WDS:
  		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
  			return -ENOLINK;
  		break;
665c93a93   Johannes Berg   mac80211: add sup...
180
181
  	case NL80211_IFTYPE_AP_VLAN: {
  		struct ieee80211_sub_if_data *master;
0d143fe1e   Johannes Berg   mac80211: move re...
182
183
  		if (!sdata->bss)
  			return -ENOLINK;
665c93a93   Johannes Berg   mac80211: add sup...
184

0d143fe1e   Johannes Berg   mac80211: move re...
185
  		list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
665c93a93   Johannes Berg   mac80211: add sup...
186
187
188
189
190
191
192
  
  		master = container_of(sdata->bss,
  				      struct ieee80211_sub_if_data, u.ap);
  		sdata->control_port_protocol =
  			master->control_port_protocol;
  		sdata->control_port_no_encrypt =
  			master->control_port_no_encrypt;
0d143fe1e   Johannes Berg   mac80211: move re...
193
  		break;
665c93a93   Johannes Berg   mac80211: add sup...
194
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
195
196
197
198
  	case NL80211_IFTYPE_AP:
  		sdata->bss = &sdata->u.ap;
  		break;
  	case NL80211_IFTYPE_MESH_POINT:
0d143fe1e   Johannes Berg   mac80211: move re...
199
200
201
202
203
204
  	case NL80211_IFTYPE_STATION:
  	case NL80211_IFTYPE_MONITOR:
  	case NL80211_IFTYPE_ADHOC:
  		/* no special treatment */
  		break;
  	case NL80211_IFTYPE_UNSPECIFIED:
2e161f78e   Johannes Berg   cfg80211/mac80211...
205
  	case NUM_NL80211_IFTYPES:
2ca27bcff   Johannes Berg   mac80211: add p2p...
206
207
  	case NL80211_IFTYPE_P2P_CLIENT:
  	case NL80211_IFTYPE_P2P_GO:
0d143fe1e   Johannes Berg   mac80211: move re...
208
209
210
211
212
213
  		/* cannot happen */
  		WARN_ON(1);
  		break;
  	}
  
  	if (local->open_count == 0) {
244879813   Johannes Berg   mac80211: add dri...
214
  		res = drv_start(local);
0d143fe1e   Johannes Berg   mac80211: move re...
215
216
  		if (res)
  			goto err_del_bss;
4e6cbfd09   John W. Linville   mac80211: support...
217
218
  		if (local->ops->napi_poll)
  			napi_enable(&local->napi);
e8975581f   Johannes Berg   mac80211: introdu...
219
220
  		/* we're brought up, everything changes */
  		hw_reconf_flags = ~0;
1f87f7d3a   Johannes Berg   cfg80211: add rfk...
221
  		ieee80211_led_radio(local, true);
67408c8c7   Johannes Berg   mac80211: selecti...
222
223
  		ieee80211_mod_tpt_led_trig(local,
  					   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
0d143fe1e   Johannes Berg   mac80211: move re...
224
225
226
  	}
  
  	/*
bf533e0bf   Johannes Berg   mac80211: simplif...
227
228
  	 * Copy the hopefully now-present MAC address to
  	 * this interface, if it has the special null one.
0d143fe1e   Johannes Berg   mac80211: move re...
229
  	 */
bf533e0bf   Johannes Berg   mac80211: simplif...
230
231
232
233
234
235
236
237
238
239
  	if (is_zero_ether_addr(dev->dev_addr)) {
  		memcpy(dev->dev_addr,
  		       local->hw.wiphy->perm_addr,
  		       ETH_ALEN);
  		memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
  
  		if (!is_valid_ether_addr(dev->dev_addr)) {
  			if (!local->open_count)
  				drv_stop(local);
  			return -EADDRNOTAVAIL;
0adc23f58   John W. Linville   mac80211: support...
240
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
241
  	}
0d143fe1e   Johannes Berg   mac80211: move re...
242
243
244
245
246
247
248
249
250
251
252
253
  	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...
254
  		if (local->monitors == 1) {
0869aea0e   Johannes Berg   mac80211: remove ...
255
256
  			local->hw.conf.flags |= IEEE80211_CONF_MONITOR;
  			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
e8975581f   Johannes Berg   mac80211: introdu...
257
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
258

85416a4fa   Christian Lamparter   mac80211: fix rx ...
259
  		ieee80211_adjust_monitor_flags(sdata, 1);
0d143fe1e   Johannes Berg   mac80211: move re...
260
  		ieee80211_configure_filter(local);
53e9b1de6   David Gnedt   mac80211: set car...
261
262
  
  		netif_carrier_on(dev);
0d143fe1e   Johannes Berg   mac80211: move re...
263
  		break;
0d143fe1e   Johannes Berg   mac80211: move re...
264
  	default:
34d4bc4d4   Johannes Berg   mac80211: support...
265
  		if (coming_up) {
7b7eab6fc   Johannes Berg   mac80211: verify ...
266
  			res = drv_add_interface(local, sdata);
34d4bc4d4   Johannes Berg   mac80211: support...
267
268
269
  			if (res)
  				goto err_stop;
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
270

29cbe68c5   Johannes Berg   cfg80211/mac80211...
271
  		if (sdata->vif.type == NL80211_IFTYPE_AP) {
e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
272
  			local->fif_pspoll++;
7be5086d4   Johannes Berg   mac80211: add pro...
273
  			local->fif_probe_req++;
e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
274

e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
275
  			ieee80211_configure_filter(local);
7be5086d4   Johannes Berg   mac80211: add pro...
276
277
  		} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
  			local->fif_probe_req++;
a3c9aa512   Andrey Yurovsky   mac80211: disable...
278
  		}
e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
279

0d143fe1e   Johannes Berg   mac80211: move re...
280
281
  		changed |= ieee80211_reset_erp_info(sdata);
  		ieee80211_bss_info_change_notify(sdata, changed);
0d143fe1e   Johannes Berg   mac80211: move re...
282

86a2ea413   Eliad Peller   mac80211: set car...
283
284
  		if (sdata->vif.type == NL80211_IFTYPE_STATION ||
  		    sdata->vif.type == NL80211_IFTYPE_ADHOC)
0d143fe1e   Johannes Berg   mac80211: move re...
285
286
287
  			netif_carrier_off(dev);
  		else
  			netif_carrier_on(dev);
590345910   Eliad Peller   mac80211: call se...
288
289
290
291
292
293
294
  
  		/*
  		 * 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);
0d143fe1e   Johannes Berg   mac80211: move re...
295
  	}
2d2080c3c   Johannes Berg   mac80211: set run...
296
  	set_bit(SDATA_STATE_RUNNING, &sdata->state);
0d143fe1e   Johannes Berg   mac80211: move re...
297
298
299
300
301
302
303
304
  	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;
  		}
d9a7ddb05   Johannes Berg   mac80211: refacto...
305
306
307
  		sta_info_move_state(sta, IEEE80211_STA_AUTH);
  		sta_info_move_state(sta, IEEE80211_STA_ASSOC);
  		sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
0d143fe1e   Johannes Berg   mac80211: move re...
308
309
310
311
312
313
  
  		res = sta_info_insert(sta);
  		if (res) {
  			/* STA has been freed */
  			goto err_del_interface;
  		}
1be7fe8de   Bill Jordan   mac80211: fix for...
314
315
  
  		rate_control_rate_init(sta);
0d143fe1e   Johannes Berg   mac80211: move re...
316
  	}
0d143fe1e   Johannes Berg   mac80211: move re...
317
318
319
320
321
322
323
324
325
326
  	/*
  	 * 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);
7da7cc1d4   Johannes Berg   mac80211: per int...
327
  	mutex_lock(&local->mtx);
5cff20e6c   Johannes Berg   mac80211: tell dr...
328
  	hw_reconf_flags |= __ieee80211_recalc_idle(local);
7da7cc1d4   Johannes Berg   mac80211: per int...
329
  	mutex_unlock(&local->mtx);
5cff20e6c   Johannes Berg   mac80211: tell dr...
330

34d4bc4d4   Johannes Berg   mac80211: support...
331
332
  	if (coming_up)
  		local->open_count++;
590345910   Eliad Peller   mac80211: call se...
333
  	if (hw_reconf_flags)
e8975581f   Johannes Berg   mac80211: introdu...
334
  		ieee80211_hw_config(local, hw_reconf_flags);
0d143fe1e   Johannes Berg   mac80211: move re...
335

10f644a47   Johannes Berg   mac80211: disable...
336
  	ieee80211_recalc_ps(local, -1);
965bedadc   Johannes Berg   mac80211: improve...
337

8a5b33f55   John W. Linville   Revert "mac80211:...
338
  	netif_tx_start_all_queues(dev);
0d143fe1e   Johannes Berg   mac80211: move re...
339
340
341
  
  	return 0;
   err_del_interface:
7b7eab6fc   Johannes Berg   mac80211: verify ...
342
  	drv_remove_interface(local, sdata);
0d143fe1e   Johannes Berg   mac80211: move re...
343
   err_stop:
244879813   Johannes Berg   mac80211: add dri...
344
345
  	if (!local->open_count)
  		drv_stop(local);
0d143fe1e   Johannes Berg   mac80211: move re...
346
347
348
349
   err_del_bss:
  	sdata->bss = NULL;
  	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
  		list_del(&sdata->u.vlan.list);
2d2080c3c   Johannes Berg   mac80211: set run...
350
  	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
0d143fe1e   Johannes Berg   mac80211: move re...
351
352
  	return res;
  }
34d4bc4d4   Johannes Berg   mac80211: support...
353
  static int ieee80211_open(struct net_device *dev)
0d143fe1e   Johannes Berg   mac80211: move re...
354
355
  {
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
34d4bc4d4   Johannes Berg   mac80211: support...
356
357
358
  	int err;
  
  	/* fail early if user set an invalid address */
2fcf28247   Mohammed Shafi Shajakhan   mac80211: remove ...
359
  	if (!is_valid_ether_addr(dev->dev_addr))
34d4bc4d4   Johannes Berg   mac80211: support...
360
361
362
363
364
365
366
367
368
369
370
371
  		return -EADDRNOTAVAIL;
  
  	err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
  	if (err)
  		return err;
  
  	return ieee80211_do_open(dev, true);
  }
  
  static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
  			      bool going_down)
  {
0d143fe1e   Johannes Berg   mac80211: move re...
372
  	struct ieee80211_local *local = sdata->local;
5061b0c2b   Johannes Berg   mac80211: coopera...
373
374
  	unsigned long flags;
  	struct sk_buff *skb, *tmp;
e8975581f   Johannes Berg   mac80211: introdu...
375
  	u32 hw_reconf_flags = 0;
5061b0c2b   Johannes Berg   mac80211: coopera...
376
  	int i;
2cf22b897   Ben Greear   mac80211: Recalcu...
377
  	enum nl80211_channel_type orig_ct;
0d143fe1e   Johannes Berg   mac80211: move re...
378

c29acf201   Rajkumar Manoharan   mac80211: abort s...
379
  	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
352ffad64   Brian Cavagnolo   mac80211: unset S...
380
381
  	if (local->scan_sdata == sdata)
  		ieee80211_scan_cancel(local);
0d143fe1e   Johannes Berg   mac80211: move re...
382
383
384
  	/*
  	 * Stop TX on this interface first.
  	 */
34d4bc4d4   Johannes Berg   mac80211: support...
385
  	netif_tx_stop_all_queues(sdata->dev);
0d143fe1e   Johannes Berg   mac80211: move re...
386
387
  
  	/*
af6b63741   Johannes Berg   mac80211: general...
388
389
390
391
392
  	 * Purge work for this interface.
  	 */
  	ieee80211_work_purge(sdata);
  
  	/*
0d143fe1e   Johannes Berg   mac80211: move re...
393
394
395
396
397
398
399
400
401
  	 * 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!)
  	 *
b9dcf712d   Johannes Berg   mac80211: clean u...
402
403
404
  	 * This is relevant only in AP, WDS and mesh modes, since in
  	 * all other modes we've already removed all stations when
  	 * disconnecting etc.
0d143fe1e   Johannes Berg   mac80211: move re...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
  	 */
  	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);
7be5086d4   Johannes Berg   mac80211: add pro...
419
  	if (sdata->vif.type == NL80211_IFTYPE_AP) {
e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
420
  		local->fif_pspoll--;
7be5086d4   Johannes Berg   mac80211: add pro...
421
422
423
424
  		local->fif_probe_req--;
  	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
  		local->fif_probe_req--;
  	}
e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
425

34d4bc4d4   Johannes Berg   mac80211: support...
426
  	netif_addr_lock_bh(sdata->dev);
3b8d81e02   Johannes Berg   mac80211: remove ...
427
  	spin_lock_bh(&local->filter_lock);
34d4bc4d4   Johannes Berg   mac80211: support...
428
429
  	__hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
  			 sdata->dev->addr_len);
3b8d81e02   Johannes Berg   mac80211: remove ...
430
  	spin_unlock_bh(&local->filter_lock);
34d4bc4d4   Johannes Berg   mac80211: support...
431
  	netif_addr_unlock_bh(sdata->dev);
3b8d81e02   Johannes Berg   mac80211: remove ...
432

3ac64beec   Johannes Berg   mac80211: allow c...
433
  	ieee80211_configure_filter(local);
7cbf0ba51   Vivek Natarajan   mac80211: Cancel ...
434
435
  	del_timer_sync(&local->dynamic_ps_timer);
  	cancel_work_sync(&local->dynamic_ps_enable_work);
0d143fe1e   Johannes Berg   mac80211: move re...
436
437
438
  
  	/* APs need special treatment */
  	if (sdata->vif.type == NL80211_IFTYPE_AP) {
57c9fff3d   Johannes Berg   mac80211: fix spa...
439
  		struct ieee80211_sub_if_data *vlan, *tmpsdata;
40b275b69   Johannes Berg   mac80211: sparse ...
440
441
  		struct beacon_data *old_beacon =
  			rtnl_dereference(sdata->u.ap.beacon);
029458212   Arik Nemtsov   mac80211: Save pr...
442
443
  		struct sk_buff *old_probe_resp =
  			rtnl_dereference(sdata->u.ap.probe_resp);
0d143fe1e   Johannes Berg   mac80211: move re...
444

b9dcf712d   Johannes Berg   mac80211: clean u...
445
446
447
  		/* sdata_running will return false, so this will disable */
  		ieee80211_bss_info_change_notify(sdata,
  						 BSS_CHANGED_BEACON_ENABLED);
029458212   Arik Nemtsov   mac80211: Save pr...
448
  		/* remove beacon and probe response */
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
449
  		RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
029458212   Arik Nemtsov   mac80211: Save pr...
450
  		RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
0d143fe1e   Johannes Berg   mac80211: move re...
451
452
  		synchronize_rcu();
  		kfree(old_beacon);
5e2e05de5   Dan Carpenter   mac80211: use kfr...
453
  		kfree_skb(old_probe_resp);
0d143fe1e   Johannes Berg   mac80211: move re...
454
455
  
  		/* down all dependent devices, that is VLANs */
57c9fff3d   Johannes Berg   mac80211: fix spa...
456
  		list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
0d143fe1e   Johannes Berg   mac80211: move re...
457
458
459
  					 u.vlan.list)
  			dev_close(vlan->dev);
  		WARN_ON(!list_empty(&sdata->u.ap.vlans));
6f2d93353   Johannes Berg   mac80211: fix AP/...
460
461
462
463
  
  		/* free all potentially still buffered bcast frames */
  		local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
  		skb_queue_purge(&sdata->u.ap.ps_bc_buf);
0d143fe1e   Johannes Berg   mac80211: move re...
464
  	}
34d4bc4d4   Johannes Berg   mac80211: support...
465
466
  	if (going_down)
  		local->open_count--;
0d143fe1e   Johannes Berg   mac80211: move re...
467
468
469
470
471
472
473
474
475
476
477
478
479
  
  	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...
480
  		if (local->monitors == 0) {
0869aea0e   Johannes Berg   mac80211: remove ...
481
482
  			local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
  			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
e8975581f   Johannes Berg   mac80211: introdu...
483
  		}
0d143fe1e   Johannes Berg   mac80211: move re...
484

85416a4fa   Christian Lamparter   mac80211: fix rx ...
485
  		ieee80211_adjust_monitor_flags(sdata, -1);
0d143fe1e   Johannes Berg   mac80211: move re...
486
  		ieee80211_configure_filter(local);
0d143fe1e   Johannes Berg   mac80211: move re...
487
  		break;
0d143fe1e   Johannes Berg   mac80211: move re...
488
  	default:
c1475ca99   Johannes Berg   mac80211: move ag...
489
  		flush_work(&sdata->work);
35f20c14a   Johannes Berg   mac80211: use com...
490
491
492
493
494
495
496
497
  		/*
  		 * 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();
  		skb_queue_purge(&sdata->skb_queue);
97af74320   Bob Copeland   mac80211: disable...
498
  		/*
b9dcf712d   Johannes Berg   mac80211: clean u...
499
500
  		 * Disable beaconing here for mesh only, AP and IBSS
  		 * are already taken care of.
97af74320   Bob Copeland   mac80211: disable...
501
  		 */
b9dcf712d   Johannes Berg   mac80211: clean u...
502
  		if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
97af74320   Bob Copeland   mac80211: disable...
503
504
  			ieee80211_bss_info_change_notify(sdata,
  				BSS_CHANGED_BEACON_ENABLED);
97af74320   Bob Copeland   mac80211: disable...
505

b9dcf712d   Johannes Berg   mac80211: clean u...
506
507
508
509
  		/*
  		 * Free all remaining keys, there shouldn't be any,
  		 * except maybe group keys in AP more or WDS?
  		 */
ad0e2b5a0   Johannes Berg   mac80211: simplif...
510
  		ieee80211_free_keys(sdata);
b9dcf712d   Johannes Berg   mac80211: clean u...
511

34d4bc4d4   Johannes Berg   mac80211: support...
512
  		if (going_down)
7b7eab6fc   Johannes Berg   mac80211: verify ...
513
  			drv_remove_interface(local, sdata);
0d143fe1e   Johannes Berg   mac80211: move re...
514
515
516
  	}
  
  	sdata->bss = NULL;
7da7cc1d4   Johannes Berg   mac80211: per int...
517
  	mutex_lock(&local->mtx);
5cff20e6c   Johannes Berg   mac80211: tell dr...
518
  	hw_reconf_flags |= __ieee80211_recalc_idle(local);
7da7cc1d4   Johannes Berg   mac80211: per int...
519
  	mutex_unlock(&local->mtx);
5cff20e6c   Johannes Berg   mac80211: tell dr...
520
521
  
  	ieee80211_recalc_ps(local, -1);
0d143fe1e   Johannes Berg   mac80211: move re...
522
  	if (local->open_count == 0) {
4e6cbfd09   John W. Linville   mac80211: support...
523
524
  		if (local->ops->napi_poll)
  			napi_disable(&local->napi);
ea77f12f2   Johannes Berg   mac80211: remove ...
525
  		ieee80211_clear_tx_pending(local);
84f6a01ce   Johannes Berg   mac80211: fix con...
526
  		ieee80211_stop_device(local);
0d143fe1e   Johannes Berg   mac80211: move re...
527

e8975581f   Johannes Berg   mac80211: introdu...
528
529
  		/* no reconfiguring after stop! */
  		hw_reconf_flags = 0;
0d143fe1e   Johannes Berg   mac80211: move re...
530
  	}
2cf22b897   Ben Greear   mac80211: Recalcu...
531
532
533
534
535
  	/* Re-calculate channel-type, in case there are multiple vifs
  	 * on different channel types.
  	 */
  	orig_ct = local->_oper_channel_type;
  	ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT);
e8975581f   Johannes Berg   mac80211: introdu...
536
  	/* do after stop to avoid reconfiguring when we stop anyway */
2cf22b897   Ben Greear   mac80211: Recalcu...
537
  	if (hw_reconf_flags || (orig_ct != local->_oper_channel_type))
e8975581f   Johannes Berg   mac80211: introdu...
538
  		ieee80211_hw_config(local, hw_reconf_flags);
5061b0c2b   Johannes Berg   mac80211: coopera...
539
540
541
542
543
544
545
546
547
548
549
  	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
  	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
  		skb_queue_walk_safe(&local->pending[i], skb, tmp) {
  			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  			if (info->control.vif == &sdata->vif) {
  				__skb_unlink(skb, &local->pending[i]);
  				dev_kfree_skb_irq(skb);
  			}
  		}
  	}
  	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
34d4bc4d4   Johannes Berg   mac80211: support...
550
551
552
553
554
555
556
  }
  
  static int ieee80211_stop(struct net_device *dev)
  {
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  
  	ieee80211_do_stop(sdata, true);
5061b0c2b   Johannes Berg   mac80211: coopera...
557

0d143fe1e   Johannes Berg   mac80211: move re...
558
559
560
561
562
  	return 0;
  }
  
  static void ieee80211_set_multicast_list(struct net_device *dev)
  {
0d143fe1e   Johannes Berg   mac80211: move re...
563
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
b4a4bf5d7   Johannes Berg   mac80211: fixups ...
564
  	struct ieee80211_local *local = sdata->local;
0d143fe1e   Johannes Berg   mac80211: move re...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  	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;
  	}
3b8d81e02   Johannes Berg   mac80211: remove ...
587
  	spin_lock_bh(&local->filter_lock);
22bedad3c   Jiri Pirko   net: convert mult...
588
  	__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
3b8d81e02   Johannes Berg   mac80211: remove ...
589
  	spin_unlock_bh(&local->filter_lock);
3ac64beec   Johannes Berg   mac80211: allow c...
590
  	ieee80211_queue_work(&local->hw, &local->reconfig_filter);
0d143fe1e   Johannes Berg   mac80211: move re...
591
  }
75636525f   Johannes Berg   mac80211: revamp ...
592
593
594
595
596
  /*
   * 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...
597
  {
75636525f   Johannes Berg   mac80211: revamp ...
598
599
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	struct ieee80211_local *local = sdata->local;
75636525f   Johannes Berg   mac80211: revamp ...
600
  	int flushed;
f0706e828   Jiri Benc   [MAC80211]: Add m...
601
  	int i;
75636525f   Johannes Berg   mac80211: revamp ...
602
603
  	/* free extra data */
  	ieee80211_free_keys(sdata);
aee14ceb5   Jouni Malinen   mac80211: Reorder...
604
  	ieee80211_debugfs_remove_netdev(sdata);
f0706e828   Jiri Benc   [MAC80211]: Add m...
605
  	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
75636525f   Johannes Berg   mac80211: revamp ...
606
607
  		__skb_queue_purge(&sdata->fragments[i].skb_list);
  	sdata->fragment_next = 0;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
608

b9dcf712d   Johannes Berg   mac80211: clean u...
609
610
  	if (ieee80211_vif_is_mesh(&sdata->vif))
  		mesh_rmc_free(sdata);
75636525f   Johannes Berg   mac80211: revamp ...
611
612
613
  
  	flushed = sta_info_flush(local, sdata);
  	WARN_ON(flushed);
f0706e828   Jiri Benc   [MAC80211]: Add m...
614
  }
cf0277e71   Johannes Berg   mac80211: fix skb...
615
616
617
618
619
  static u16 ieee80211_netdev_select_queue(struct net_device *dev,
  					 struct sk_buff *skb)
  {
  	return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
  }
587e729ec   Johannes Berg   mac80211: convert...
620
621
622
623
624
  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,
afc4b13df   Jiri Pirko   net: remove use o...
625
  	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
587e729ec   Johannes Berg   mac80211: convert...
626
  	.ndo_change_mtu 	= ieee80211_change_mtu,
47846c9b0   Johannes Berg   mac80211: reduce ...
627
  	.ndo_set_mac_address 	= ieee80211_change_mac,
cf0277e71   Johannes Berg   mac80211: fix skb...
628
  	.ndo_select_queue	= ieee80211_netdev_select_queue,
587e729ec   Johannes Berg   mac80211: convert...
629
  };
cf0277e71   Johannes Berg   mac80211: fix skb...
630
631
632
633
634
635
636
637
638
639
640
641
  static u16 ieee80211_monitor_select_queue(struct net_device *dev,
  					  struct sk_buff *skb)
  {
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	struct ieee80211_local *local = sdata->local;
  	struct ieee80211_hdr *hdr;
  	struct ieee80211_radiotap_header *rtap = (void *)skb->data;
  
  	if (local->hw.queues < 4)
  		return 0;
  
  	if (skb->len < 4 ||
b49bb574e   Johannes Berg   mac80211: fix end...
642
  	    skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
cf0277e71   Johannes Berg   mac80211: fix skb...
643
  		return 0; /* doesn't matter, frame will be dropped */
b49bb574e   Johannes Berg   mac80211: fix end...
644
  	hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
cf0277e71   Johannes Berg   mac80211: fix skb...
645

d3c1597b8   Thomas Pedersen   mac80211: fix for...
646
  	return ieee80211_select_queue_80211(local, skb, hdr);
cf0277e71   Johannes Berg   mac80211: fix skb...
647
  }
587e729ec   Johannes Berg   mac80211: convert...
648
649
650
651
652
  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,
afc4b13df   Jiri Pirko   net: remove use o...
653
  	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
587e729ec   Johannes Berg   mac80211: convert...
654
655
  	.ndo_change_mtu 	= ieee80211_change_mtu,
  	.ndo_set_mac_address 	= eth_mac_addr,
cf0277e71   Johannes Berg   mac80211: fix skb...
656
  	.ndo_select_queue	= ieee80211_monitor_select_queue,
587e729ec   Johannes Berg   mac80211: convert...
657
658
659
660
661
  };
  
  static void ieee80211_if_setup(struct net_device *dev)
  {
  	ether_setup(dev);
550fd08c2   Neil Horman   net: Audit driver...
662
  	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
587e729ec   Johannes Berg   mac80211: convert...
663
  	dev->netdev_ops = &ieee80211_dataif_ops;
587e729ec   Johannes Berg   mac80211: convert...
664
665
  	dev->destructor = free_netdev;
  }
1fa57d017   Johannes Berg   mac80211: use com...
666
667
668
669
670
671
  static void ieee80211_iface_work(struct work_struct *work)
  {
  	struct ieee80211_sub_if_data *sdata =
  		container_of(work, struct ieee80211_sub_if_data, work);
  	struct ieee80211_local *local = sdata->local;
  	struct sk_buff *skb;
344eec67c   Johannes Berg   mac80211: move bl...
672
  	struct sta_info *sta;
c1475ca99   Johannes Berg   mac80211: move ag...
673
  	struct ieee80211_ra_tid *ra_tid;
1fa57d017   Johannes Berg   mac80211: use com...
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  
  	if (!ieee80211_sdata_running(sdata))
  		return;
  
  	if (local->scanning)
  		return;
  
  	/*
  	 * ieee80211_queue_work() should have picked up most cases,
  	 * here we'll pick the rest.
  	 */
  	if (WARN(local->suspended,
  		 "interface work scheduled while going to suspend
  "))
  		return;
  
  	/* first process frames */
  	while ((skb = skb_dequeue(&sdata->skb_queue))) {
bed7ee6e4   Johannes Berg   mac80211: always ...
692
  		struct ieee80211_mgmt *mgmt = (void *)skb->data;
c1475ca99   Johannes Berg   mac80211: move ag...
693
694
695
696
697
698
699
700
701
702
  		if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) {
  			ra_tid = (void *)&skb->cb;
  			ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra,
  						 ra_tid->tid);
  		} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_STOP) {
  			ra_tid = (void *)&skb->cb;
  			ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra,
  						ra_tid->tid);
  		} else if (ieee80211_is_action(mgmt->frame_control) &&
  			   mgmt->u.action.category == WLAN_CATEGORY_BACK) {
bed7ee6e4   Johannes Berg   mac80211: always ...
703
  			int len = skb->len;
bed7ee6e4   Johannes Berg   mac80211: always ...
704

a93e36443   Johannes Berg   mac80211: change ...
705
  			mutex_lock(&local->sta_mtx);
875ae5f68   Felix Fietkau   mac80211: fix agg...
706
  			sta = sta_info_get_bss(sdata, mgmt->sa);
bed7ee6e4   Johannes Berg   mac80211: always ...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
  			if (sta) {
  				switch (mgmt->u.action.u.addba_req.action_code) {
  				case WLAN_ACTION_ADDBA_REQ:
  					ieee80211_process_addba_request(
  							local, sta, mgmt, len);
  					break;
  				case WLAN_ACTION_ADDBA_RESP:
  					ieee80211_process_addba_resp(local, sta,
  								     mgmt, len);
  					break;
  				case WLAN_ACTION_DELBA:
  					ieee80211_process_delba(sdata, sta,
  								mgmt, len);
  					break;
  				default:
  					WARN_ON(1);
  					break;
  				}
  			}
a93e36443   Johannes Berg   mac80211: change ...
726
  			mutex_unlock(&local->sta_mtx);
344eec67c   Johannes Berg   mac80211: move bl...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  		} else if (ieee80211_is_data_qos(mgmt->frame_control)) {
  			struct ieee80211_hdr *hdr = (void *)mgmt;
  			/*
  			 * So the frame isn't mgmt, but frame_control
  			 * is at the right place anyway, of course, so
  			 * the if statement is correct.
  			 *
  			 * Warn if we have other data frame types here,
  			 * they must not get here.
  			 */
  			WARN_ON(hdr->frame_control &
  					cpu_to_le16(IEEE80211_STYPE_NULLFUNC));
  			WARN_ON(!(hdr->seq_ctrl &
  					cpu_to_le16(IEEE80211_SCTL_FRAG)));
  			/*
  			 * This was a fragment of a frame, received while
  			 * a block-ack session was active. That cannot be
  			 * right, so terminate the session.
  			 */
a93e36443   Johannes Berg   mac80211: change ...
746
  			mutex_lock(&local->sta_mtx);
875ae5f68   Felix Fietkau   mac80211: fix agg...
747
  			sta = sta_info_get_bss(sdata, mgmt->sa);
344eec67c   Johannes Berg   mac80211: move bl...
748
749
750
751
752
753
  			if (sta) {
  				u16 tid = *ieee80211_get_qos_ctl(hdr) &
  						IEEE80211_QOS_CTL_TID_MASK;
  
  				__ieee80211_stop_rx_ba_session(
  					sta, tid, WLAN_BACK_RECIPIENT,
53f73c09d   Johannes Berg   mac80211: avoid t...
754
755
  					WLAN_REASON_QSTA_REQUIRE_SETUP,
  					true);
344eec67c   Johannes Berg   mac80211: move bl...
756
  			}
a93e36443   Johannes Berg   mac80211: change ...
757
  			mutex_unlock(&local->sta_mtx);
bed7ee6e4   Johannes Berg   mac80211: always ...
758
  		} else switch (sdata->vif.type) {
1fa57d017   Johannes Berg   mac80211: use com...
759
760
761
762
763
764
765
766
767
768
769
770
771
  		case NL80211_IFTYPE_STATION:
  			ieee80211_sta_rx_queued_mgmt(sdata, skb);
  			break;
  		case NL80211_IFTYPE_ADHOC:
  			ieee80211_ibss_rx_queued_mgmt(sdata, skb);
  			break;
  		case NL80211_IFTYPE_MESH_POINT:
  			if (!ieee80211_vif_is_mesh(&sdata->vif))
  				break;
  			ieee80211_mesh_rx_queued_mgmt(sdata, skb);
  			break;
  		default:
  			WARN(1, "frame for unexpected interface type");
1fa57d017   Johannes Berg   mac80211: use com...
772
773
  			break;
  		}
36b3a628a   Johannes Berg   mac80211: common ...
774
775
  
  		kfree_skb(skb);
1fa57d017   Johannes Berg   mac80211: use com...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
  	}
  
  	/* then other type-dependent work */
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_STATION:
  		ieee80211_sta_work(sdata);
  		break;
  	case NL80211_IFTYPE_ADHOC:
  		ieee80211_ibss_work(sdata);
  		break;
  	case NL80211_IFTYPE_MESH_POINT:
  		if (!ieee80211_vif_is_mesh(&sdata->vif))
  			break;
  		ieee80211_mesh_work(sdata);
  		break;
  	default:
  		break;
  	}
  }
75636525f   Johannes Berg   mac80211: revamp ...
795
796
797
798
  /*
   * 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...
799
  				  enum nl80211_iftype type)
f0706e828   Jiri Benc   [MAC80211]: Add m...
800
  {
75636525f   Johannes Berg   mac80211: revamp ...
801
802
803
804
805
  	/* clear type-dependent union */
  	memset(&sdata->u, 0, sizeof(sdata->u));
  
  	/* and set some type-dependent values */
  	sdata->vif.type = type;
2ca27bcff   Johannes Berg   mac80211: add p2p...
806
  	sdata->vif.p2p = false;
587e729ec   Johannes Berg   mac80211: convert...
807
  	sdata->dev->netdev_ops = &ieee80211_dataif_ops;
60719ffd7   Johannes Berg   cfg80211: show in...
808
  	sdata->wdev.iftype = type;
75636525f   Johannes Berg   mac80211: revamp ...
809

a621fa4d6   Johannes Berg   mac80211: allow c...
810
811
  	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
  	sdata->control_port_no_encrypt = false;
b53be7920   Simon Wunderlich   mac80211: Add NoA...
812
  	sdata->noack_map = 0;
75636525f   Johannes Berg   mac80211: revamp ...
813
814
  	/* only monitor differs */
  	sdata->dev->type = ARPHRD_ETHER;
35f20c14a   Johannes Berg   mac80211: use com...
815
  	skb_queue_head_init(&sdata->skb_queue);
1fa57d017   Johannes Berg   mac80211: use com...
816
  	INIT_WORK(&sdata->work, ieee80211_iface_work);
35f20c14a   Johannes Berg   mac80211: use com...
817

75636525f   Johannes Berg   mac80211: revamp ...
818
  	switch (type) {
2ca27bcff   Johannes Berg   mac80211: add p2p...
819
820
821
822
823
  	case NL80211_IFTYPE_P2P_GO:
  		type = NL80211_IFTYPE_AP;
  		sdata->vif.type = type;
  		sdata->vif.p2p = true;
  		/* fall through */
05c914fe3   Johannes Berg   mac80211: use nl8...
824
  	case NL80211_IFTYPE_AP:
75636525f   Johannes Berg   mac80211: revamp ...
825
826
827
  		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
  		INIT_LIST_HEAD(&sdata->u.ap.vlans);
  		break;
2ca27bcff   Johannes Berg   mac80211: add p2p...
828
829
830
831
832
  	case NL80211_IFTYPE_P2P_CLIENT:
  		type = NL80211_IFTYPE_STATION;
  		sdata->vif.type = type;
  		sdata->vif.p2p = true;
  		/* fall through */
05c914fe3   Johannes Berg   mac80211: use nl8...
833
  	case NL80211_IFTYPE_STATION:
9c6bd7901   Johannes Berg   mac80211: reorder...
834
  		ieee80211_sta_setup_sdata(sdata);
472dbc45d   Johannes Berg   mac80211: split o...
835
  		break;
469002983   Johannes Berg   mac80211: split I...
836
837
838
  	case NL80211_IFTYPE_ADHOC:
  		ieee80211_ibss_setup_sdata(sdata);
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
839
  	case NL80211_IFTYPE_MESH_POINT:
75636525f   Johannes Berg   mac80211: revamp ...
840
841
842
  		if (ieee80211_vif_is_mesh(&sdata->vif))
  			ieee80211_mesh_init_sdata(sdata);
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
843
  	case NL80211_IFTYPE_MONITOR:
75636525f   Johannes Berg   mac80211: revamp ...
844
  		sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
587e729ec   Johannes Berg   mac80211: convert...
845
  		sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
75636525f   Johannes Berg   mac80211: revamp ...
846
847
848
  		sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
  				      MONITOR_FLAG_OTHER_BSS;
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
849
850
  	case NL80211_IFTYPE_WDS:
  	case NL80211_IFTYPE_AP_VLAN:
75636525f   Johannes Berg   mac80211: revamp ...
851
  		break;
05c914fe3   Johannes Berg   mac80211: use nl8...
852
  	case NL80211_IFTYPE_UNSPECIFIED:
2e161f78e   Johannes Berg   cfg80211/mac80211...
853
  	case NUM_NL80211_IFTYPES:
75636525f   Johannes Berg   mac80211: revamp ...
854
855
856
857
858
859
  		BUG();
  		break;
  	}
  
  	ieee80211_debugfs_add_netdev(sdata);
  }
34d4bc4d4   Johannes Berg   mac80211: support...
860
861
862
863
864
  static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
  					   enum nl80211_iftype type)
  {
  	struct ieee80211_local *local = sdata->local;
  	int ret, err;
2ca27bcff   Johannes Berg   mac80211: add p2p...
865
866
  	enum nl80211_iftype internal_type = type;
  	bool p2p = false;
34d4bc4d4   Johannes Berg   mac80211: support...
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
  
  	ASSERT_RTNL();
  
  	if (!local->ops->change_interface)
  		return -EBUSY;
  
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_AP:
  	case NL80211_IFTYPE_STATION:
  	case NL80211_IFTYPE_ADHOC:
  		/*
  		 * Could maybe also all others here?
  		 * Just not sure how that interacts
  		 * with the RX/config path e.g. for
  		 * mesh.
  		 */
  		break;
  	default:
  		return -EBUSY;
  	}
  
  	switch (type) {
  	case NL80211_IFTYPE_AP:
  	case NL80211_IFTYPE_STATION:
  	case NL80211_IFTYPE_ADHOC:
  		/*
  		 * Could probably support everything
  		 * but WDS here (WDS do_open can fail
  		 * under memory pressure, which this
  		 * code isn't prepared to handle).
  		 */
  		break;
2ca27bcff   Johannes Berg   mac80211: add p2p...
899
900
901
902
903
904
905
906
  	case NL80211_IFTYPE_P2P_CLIENT:
  		p2p = true;
  		internal_type = NL80211_IFTYPE_STATION;
  		break;
  	case NL80211_IFTYPE_P2P_GO:
  		p2p = true;
  		internal_type = NL80211_IFTYPE_AP;
  		break;
34d4bc4d4   Johannes Berg   mac80211: support...
907
908
909
  	default:
  		return -EBUSY;
  	}
2ca27bcff   Johannes Berg   mac80211: add p2p...
910
  	ret = ieee80211_check_concurrent_iface(sdata, internal_type);
34d4bc4d4   Johannes Berg   mac80211: support...
911
912
913
914
915
916
  	if (ret)
  		return ret;
  
  	ieee80211_do_stop(sdata, false);
  
  	ieee80211_teardown_sdata(sdata->dev);
2ca27bcff   Johannes Berg   mac80211: add p2p...
917
  	ret = drv_change_interface(local, sdata, internal_type, p2p);
34d4bc4d4   Johannes Berg   mac80211: support...
918
919
920
921
922
923
924
925
926
927
  	if (ret)
  		type = sdata->vif.type;
  
  	ieee80211_setup_sdata(sdata, type);
  
  	err = ieee80211_do_open(sdata->dev, false);
  	WARN(err, "type change: do_open returned %d", err);
  
  	return ret;
  }
f3947e2df   Johannes Berg   mac80211: push in...
928
  int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
05c914fe3   Johannes Berg   mac80211: use nl8...
929
  			     enum nl80211_iftype type)
75636525f   Johannes Berg   mac80211: revamp ...
930
  {
34d4bc4d4   Johannes Berg   mac80211: support...
931
  	int ret;
f3947e2df   Johannes Berg   mac80211: push in...
932
  	ASSERT_RTNL();
2ca27bcff   Johannes Berg   mac80211: add p2p...
933
  	if (type == ieee80211_vif_type_p2p(&sdata->vif))
f3947e2df   Johannes Berg   mac80211: push in...
934
  		return 0;
e60c7744f   Johannes Berg   cfg80211: handle ...
935
  	/* Setting ad-hoc mode on non-IBSS channel is not supported. */
dcebf45cd   Pavel Roskin   mac80211: allow m...
936
937
  	if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS &&
  	    type == NL80211_IFTYPE_ADHOC)
e60c7744f   Johannes Berg   cfg80211: handle ...
938
  		return -EOPNOTSUPP;
34d4bc4d4   Johannes Berg   mac80211: support...
939
940
941
942
943
944
945
946
947
  	if (ieee80211_sdata_running(sdata)) {
  		ret = ieee80211_runtime_change_iftype(sdata, type);
  		if (ret)
  			return ret;
  	} else {
  		/* Purge and reset type-dependent state. */
  		ieee80211_teardown_sdata(sdata->dev);
  		ieee80211_setup_sdata(sdata, type);
  	}
75636525f   Johannes Berg   mac80211: revamp ...
948
949
  
  	/* reset some values that shouldn't be kept across type changes */
bda3933a8   Johannes Berg   mac80211: move bs...
950
  	sdata->vif.bss_conf.basic_rates =
96dd22ac0   Johannes Berg   mac80211: inform ...
951
952
  		ieee80211_mandatory_rates(sdata->local,
  			sdata->local->hw.conf.channel->band);
75636525f   Johannes Berg   mac80211: revamp ...
953
  	sdata->drop_unencrypted = 0;
9bc383de3   Johannes Berg   cfg80211: introdu...
954
955
  	if (type == NL80211_IFTYPE_STATION)
  		sdata->u.mgd.use_4addr = false;
f3947e2df   Johannes Berg   mac80211: push in...
956
957
  
  	return 0;
f0706e828   Jiri Benc   [MAC80211]: Add m...
958
  }
fa9029f8c   Johannes Berg   mac80211: use dif...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
  				       struct net_device *dev,
  				       enum nl80211_iftype type)
  {
  	struct ieee80211_sub_if_data *sdata;
  	u64 mask, start, addr, val, inc;
  	u8 *m;
  	u8 tmp_addr[ETH_ALEN];
  	int i;
  
  	/* default ... something at least */
  	memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
  
  	if (is_zero_ether_addr(local->hw.wiphy->addr_mask) &&
  	    local->hw.wiphy->n_addresses <= 1)
  		return;
  
  
  	mutex_lock(&local->iflist_mtx);
  
  	switch (type) {
  	case NL80211_IFTYPE_MONITOR:
  		/* doesn't matter */
  		break;
  	case NL80211_IFTYPE_WDS:
  	case NL80211_IFTYPE_AP_VLAN:
  		/* match up with an AP interface */
  		list_for_each_entry(sdata, &local->interfaces, list) {
  			if (sdata->vif.type != NL80211_IFTYPE_AP)
  				continue;
  			memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN);
  			break;
  		}
  		/* keep default if no AP interface present */
  		break;
  	default:
  		/* assign a new address if possible -- try n_addresses first */
  		for (i = 0; i < local->hw.wiphy->n_addresses; i++) {
  			bool used = false;
  
  			list_for_each_entry(sdata, &local->interfaces, list) {
  				if (memcmp(local->hw.wiphy->addresses[i].addr,
  					   sdata->vif.addr, ETH_ALEN) == 0) {
  					used = true;
  					break;
  				}
  			}
  
  			if (!used) {
  				memcpy(dev->perm_addr,
  				       local->hw.wiphy->addresses[i].addr,
  				       ETH_ALEN);
  				break;
  			}
  		}
  
  		/* try mask if available */
  		if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
  			break;
  
  		m = local->hw.wiphy->addr_mask;
  		mask =	((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
  			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
  			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
  
  		if (__ffs64(mask) + hweight64(mask) != fls64(mask)) {
  			/* not a contiguous mask ... not handled now! */
  			printk(KERN_DEBUG "not contiguous
  ");
  			break;
  		}
  
  		m = local->hw.wiphy->perm_addr;
  		start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
  			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
  			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
  
  		inc = 1ULL<<__ffs64(mask);
  		val = (start & mask);
  		addr = (start & ~mask) | (val & mask);
  		do {
  			bool used = false;
  
  			tmp_addr[5] = addr >> 0*8;
  			tmp_addr[4] = addr >> 1*8;
  			tmp_addr[3] = addr >> 2*8;
  			tmp_addr[2] = addr >> 3*8;
  			tmp_addr[1] = addr >> 4*8;
  			tmp_addr[0] = addr >> 5*8;
  
  			val += inc;
  
  			list_for_each_entry(sdata, &local->interfaces, list) {
  				if (memcmp(tmp_addr, sdata->vif.addr,
  							ETH_ALEN) == 0) {
  					used = true;
  					break;
  				}
  			}
  
  			if (!used) {
  				memcpy(dev->perm_addr, tmp_addr, ETH_ALEN);
  				break;
  			}
  			addr = (start & ~mask) | (val & mask);
  		} while (addr != start);
  
  		break;
  	}
  
  	mutex_unlock(&local->iflist_mtx);
  }
3e122be08   Johannes Berg   mac80211: make ma...
1071
  int ieee80211_if_add(struct ieee80211_local *local, const char *name,
05c914fe3   Johannes Berg   mac80211: use nl8...
1072
  		     struct net_device **new_dev, enum nl80211_iftype type,
ee3858551   Luis Carlos Cobo   mac80211: mesh da...
1073
  		     struct vif_params *params)
f0706e828   Jiri Benc   [MAC80211]: Add m...
1074
1075
  {
  	struct net_device *ndev;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1076
  	struct ieee80211_sub_if_data *sdata = NULL;
75636525f   Johannes Berg   mac80211: revamp ...
1077
  	int ret, i;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1078
1079
  
  	ASSERT_RTNL();
75636525f   Johannes Berg   mac80211: revamp ...
1080

55d990592   Johannes Berg   mac80211: allocat...
1081
1082
  	ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size,
  				name, ieee80211_if_setup, local->hw.queues, 1);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1083
1084
  	if (!ndev)
  		return -ENOMEM;
a272a7206   Johannes Berg   mac80211: allow u...
1085
  	dev_net_set(ndev, wiphy_net(local->hw.wiphy));
f0706e828   Jiri Benc   [MAC80211]: Add m...
1086

f3994ecee   Johannes Berg   mac80211: assign ...
1087
1088
1089
1090
1091
1092
1093
1094
  	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;
59e7e7078   Thadeu Lima de Souza Cascardo   mac80211: call de...
1095
1096
1097
  	ret = dev_alloc_name(ndev, ndev->name);
  	if (ret < 0)
  		goto fail;
fa9029f8c   Johannes Berg   mac80211: use dif...
1098
1099
  	ieee80211_assign_perm_addr(local, ndev, type);
  	memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1100
  	SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
3e122be08   Johannes Berg   mac80211: make ma...
1101
1102
  	/* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
  	sdata = netdev_priv(ndev);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1103
  	ndev->ieee80211_ptr = &sdata->wdev;
47846c9b0   Johannes Berg   mac80211: reduce ...
1104
1105
  	memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
  	memcpy(sdata->name, ndev->name, IFNAMSIZ);
75636525f   Johannes Berg   mac80211: revamp ...
1106
1107
  
  	/* initialise type-independent data */
f0706e828   Jiri Benc   [MAC80211]: Add m...
1108
  	sdata->wdev.wiphy = local->hw.wiphy;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1109
  	sdata->local = local;
75636525f   Johannes Berg   mac80211: revamp ...
1110
  	sdata->dev = ndev;
685429623   Juuso Oikarinen   mac80211: Fix cir...
1111
1112
1113
  #ifdef CONFIG_INET
  	sdata->arp_filter_state = true;
  #endif
75636525f   Johannes Berg   mac80211: revamp ...
1114
1115
1116
1117
1118
  
  	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
  		skb_queue_head_init(&sdata->fragments[i].skb_list);
  
  	INIT_LIST_HEAD(&sdata->key_list);
37eb0b164   Jouni Malinen   cfg80211/mac80211...
1119
1120
1121
1122
1123
1124
  	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
  		struct ieee80211_supported_band *sband;
  		sband = local->hw.wiphy->bands[i];
  		sdata->rc_rateidx_mask[i] =
  			sband ? (1 << sband->n_bitrates) - 1 : 0;
  	}
75636525f   Johannes Berg   mac80211: revamp ...
1125
1126
1127
  
  	/* setup type-dependent data */
  	ieee80211_setup_sdata(sdata, type);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1128

9bc383de3   Johannes Berg   cfg80211: introdu...
1129
1130
1131
1132
1133
  	if (params) {
  		ndev->ieee80211_ptr->use_4addr = params->use_4addr;
  		if (type == NL80211_IFTYPE_STATION)
  			sdata->u.mgd.use_4addr = params->use_4addr;
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
1134
1135
1136
  	ret = register_netdevice(ndev);
  	if (ret)
  		goto fail;
c771c9d8d   Johannes Berg   mac80211: add int...
1137
  	mutex_lock(&local->iflist_mtx);
79010420c   Johannes Berg   [PATCH] mac80211:...
1138
  	list_add_tail_rcu(&sdata->list, &local->interfaces);
c771c9d8d   Johannes Berg   mac80211: add int...
1139
  	mutex_unlock(&local->iflist_mtx);
79010420c   Johannes Berg   [PATCH] mac80211:...
1140

f0706e828   Jiri Benc   [MAC80211]: Add m...
1141
1142
  	if (new_dev)
  		*new_dev = ndev;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1143

f0706e828   Jiri Benc   [MAC80211]: Add m...
1144
  	return 0;
75636525f   Johannes Berg   mac80211: revamp ...
1145
   fail:
f0706e828   Jiri Benc   [MAC80211]: Add m...
1146
1147
1148
  	free_netdev(ndev);
  	return ret;
  }
f698d856f   Jasper Bryant-Greene   replace net_devic...
1149
  void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
f0706e828   Jiri Benc   [MAC80211]: Add m...
1150
  {
f0706e828   Jiri Benc   [MAC80211]: Add m...
1151
  	ASSERT_RTNL();
11a843b7e   Johannes Berg   [MAC80211]: rewor...
1152

c771c9d8d   Johannes Berg   mac80211: add int...
1153
  	mutex_lock(&sdata->local->iflist_mtx);
75636525f   Johannes Berg   mac80211: revamp ...
1154
  	list_del_rcu(&sdata->list);
c771c9d8d   Johannes Berg   mac80211: add int...
1155
  	mutex_unlock(&sdata->local->iflist_mtx);
ece1a2e7e   Javier Cardona   mac80211: Remove ...
1156
1157
  	if (ieee80211_vif_is_mesh(&sdata->vif))
  		mesh_path_flush_by_iface(sdata);
75636525f   Johannes Berg   mac80211: revamp ...
1158
  	synchronize_rcu();
f698d856f   Jasper Bryant-Greene   replace net_devic...
1159
  	unregister_netdevice(sdata->dev);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1160
  }
75636525f   Johannes Berg   mac80211: revamp ...
1161
1162
1163
1164
1165
  /*
   * 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...
1166
  {
75636525f   Johannes Berg   mac80211: revamp ...
1167
  	struct ieee80211_sub_if_data *sdata, *tmp;
efe117ab8   Eric Dumazet   mac80211: Speedup...
1168
  	LIST_HEAD(unreg_list);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1169
1170
  
  	ASSERT_RTNL();
efe117ab8   Eric Dumazet   mac80211: Speedup...
1171
  	mutex_lock(&local->iflist_mtx);
75636525f   Johannes Berg   mac80211: revamp ...
1172
1173
  	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
  		list_del(&sdata->list);
c771c9d8d   Johannes Berg   mac80211: add int...
1174

ece1a2e7e   Javier Cardona   mac80211: Remove ...
1175
1176
  		if (ieee80211_vif_is_mesh(&sdata->vif))
  			mesh_path_flush_by_iface(sdata);
efe117ab8   Eric Dumazet   mac80211: Speedup...
1177
  		unregister_netdevice_queue(sdata->dev, &unreg_list);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1178
  	}
efe117ab8   Eric Dumazet   mac80211: Speedup...
1179
1180
  	mutex_unlock(&local->iflist_mtx);
  	unregister_netdevice_many(&unreg_list);
5f04d5068   Eric W. Biederman   net: Fix more sta...
1181
  	list_del(&unreg_list);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1182
  }
5cff20e6c   Johannes Berg   mac80211: tell dr...
1183
1184
1185
1186
1187
1188
1189
1190
  
  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
0fb9a9ec2   Joe Perches   net/mac80211: Use...
1191
1192
  	wiphy_debug(local->hw.wiphy, "device no longer idle - %s
  ", reason);
5cff20e6c   Johannes Berg   mac80211: tell dr...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  #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
0fb9a9ec2   Joe Perches   net/mac80211: Use...
1205
1206
  	wiphy_debug(local->hw.wiphy, "device now idle
  ");
5cff20e6c   Johannes Berg   mac80211: tell dr...
1207
  #endif
a80f7c0b0   Johannes Berg   mac80211: introdu...
1208
  	drv_flush(local, false);
5cff20e6c   Johannes Berg   mac80211: tell dr...
1209
1210
1211
1212
1213
1214
1215
1216
  	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;
21f835896   Johannes Berg   mac80211: impleme...
1217
  	bool working = false, scanning = false, hw_roc = false;
7da7cc1d4   Johannes Berg   mac80211: per int...
1218
  	struct ieee80211_work *wk;
67408c8c7   Johannes Berg   mac80211: selecti...
1219
  	unsigned int led_trig_start = 0, led_trig_stop = 0;
5cff20e6c   Johannes Berg   mac80211: tell dr...
1220

7da7cc1d4   Johannes Berg   mac80211: per int...
1221
1222
1223
1224
1225
  #ifdef CONFIG_PROVE_LOCKING
  	WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
  		!lockdep_is_held(&local->iflist_mtx));
  #endif
  	lockdep_assert_held(&local->mtx);
5cff20e6c   Johannes Berg   mac80211: tell dr...
1226
1227
  
  	list_for_each_entry(sdata, &local->interfaces, list) {
7da7cc1d4   Johannes Berg   mac80211: per int...
1228
1229
  		if (!ieee80211_sdata_running(sdata)) {
  			sdata->vif.bss_conf.idle = true;
5cff20e6c   Johannes Berg   mac80211: tell dr...
1230
  			continue;
7da7cc1d4   Johannes Berg   mac80211: per int...
1231
1232
1233
  		}
  
  		sdata->old_idle = sdata->vif.bss_conf.idle;
5cff20e6c   Johannes Berg   mac80211: tell dr...
1234
1235
  		/* do not count disabled managed interfaces */
  		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
7da7cc1d4   Johannes Berg   mac80211: per int...
1236
1237
  		    !sdata->u.mgd.associated) {
  			sdata->vif.bss_conf.idle = true;
5cff20e6c   Johannes Berg   mac80211: tell dr...
1238
  			continue;
7da7cc1d4   Johannes Berg   mac80211: per int...
1239
  		}
5cff20e6c   Johannes Berg   mac80211: tell dr...
1240
1241
  		/* do not count unused IBSS interfaces */
  		if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
7da7cc1d4   Johannes Berg   mac80211: per int...
1242
1243
  		    !sdata->u.ibss.ssid_len) {
  			sdata->vif.bss_conf.idle = true;
5cff20e6c   Johannes Berg   mac80211: tell dr...
1244
  			continue;
7da7cc1d4   Johannes Berg   mac80211: per int...
1245
  		}
5cff20e6c   Johannes Berg   mac80211: tell dr...
1246
1247
1248
  		/* count everything else */
  		count++;
  	}
7da7cc1d4   Johannes Berg   mac80211: per int...
1249
1250
1251
1252
1253
1254
1255
1256
1257
  	list_for_each_entry(wk, &local->work_list, list) {
  		working = true;
  		wk->sdata->vif.bss_conf.idle = false;
  	}
  
  	if (local->scan_sdata) {
  		scanning = true;
  		local->scan_sdata->vif.bss_conf.idle = false;
  	}
21f835896   Johannes Berg   mac80211: impleme...
1258
1259
  	if (local->hw_roc_channel)
  		hw_roc = true;
7da7cc1d4   Johannes Berg   mac80211: per int...
1260
1261
1262
1263
1264
1265
1266
  	list_for_each_entry(sdata, &local->interfaces, list) {
  		if (sdata->old_idle == sdata->vif.bss_conf.idle)
  			continue;
  		if (!ieee80211_sdata_running(sdata))
  			continue;
  		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
  	}
21f835896   Johannes Berg   mac80211: impleme...
1267
  	if (working || scanning || hw_roc)
67408c8c7   Johannes Berg   mac80211: selecti...
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
  		led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
  	else
  		led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
  
  	if (count)
  		led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
  	else
  		led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
  
  	ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
21f835896   Johannes Berg   mac80211: impleme...
1278
1279
  	if (hw_roc)
  		return ieee80211_idle_off(local, "hw remain-on-channel");
7da7cc1d4   Johannes Berg   mac80211: per int...
1280
1281
1282
1283
  	if (working)
  		return ieee80211_idle_off(local, "working");
  	if (scanning)
  		return ieee80211_idle_off(local, "scanning");
5cff20e6c   Johannes Berg   mac80211: tell dr...
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  	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...
1299
1300
  	if (chg)
  		ieee80211_hw_config(local, chg);
5cff20e6c   Johannes Berg   mac80211: tell dr...
1301
  }
47846c9b0   Johannes Berg   mac80211: reduce ...
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  
  static int netdev_notify(struct notifier_block *nb,
  			 unsigned long state,
  			 void *ndev)
  {
  	struct net_device *dev = ndev;
  	struct ieee80211_sub_if_data *sdata;
  
  	if (state != NETDEV_CHANGENAME)
  		return 0;
  
  	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
  		return 0;
  
  	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
  		return 0;
  
  	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2f5265e6e   Johannes Berg   mac80211: fix net...
1320
  	memcpy(sdata->name, dev->name, IFNAMSIZ);
47846c9b0   Johannes Berg   mac80211: reduce ...
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
  
  	ieee80211_debugfs_rename_netdev(sdata);
  	return 0;
  }
  
  static struct notifier_block mac80211_netdev_notifier = {
  	.notifier_call = netdev_notify,
  };
  
  int ieee80211_iface_init(void)
  {
  	return register_netdevice_notifier(&mac80211_netdev_notifier);
  }
  
  void ieee80211_iface_exit(void)
  {
  	unregister_netdevice_notifier(&mac80211_netdev_notifier);
  }