Blame view

net/mac80211/main.c 29.6 KB
f0706e828   Jiri Benc   [MAC80211]: Add m...
1
2
3
4
5
6
7
8
9
10
11
  /*
   * Copyright 2002-2005, Instant802 Networks, Inc.
   * Copyright 2005-2006, Devicescape Software, Inc.
   * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
   *
   * 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 <net/mac80211.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
12
13
14
15
16
17
18
19
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/netdevice.h>
  #include <linux/types.h>
  #include <linux/slab.h>
  #include <linux/skbuff.h>
  #include <linux/etherdevice.h>
  #include <linux/if_arp.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
20
  #include <linux/rtnetlink.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
21
  #include <linux/bitmap.h>
e8db0be12   Jean Pihet   PM QoS: Move and ...
22
  #include <linux/pm_qos.h>
685429623   Juuso Oikarinen   mac80211: Fix cir...
23
  #include <linux/inetdevice.h>
881d966b4   Eric W. Biederman   [NET]: Make the d...
24
  #include <net/net_namespace.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
25
  #include <net/cfg80211.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
26
  #include "ieee80211_i.h"
244879813   Johannes Berg   mac80211: add dri...
27
  #include "driver-ops.h"
2c8dccc77   Johannes Berg   mac80211: rename ...
28
  #include "rate.h"
f7a921443   Luis Carlos Cobo   mac80211: complet...
29
  #include "mesh.h"
f0706e828   Jiri Benc   [MAC80211]: Add m...
30
  #include "wep.h"
2c8dccc77   Johannes Berg   mac80211: rename ...
31
  #include "led.h"
e0eb68596   Michael Wu   [MAC80211]: renam...
32
  #include "cfg.h"
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
33
  #include "debugfs.h"
f0706e828   Jiri Benc   [MAC80211]: Add m...
34

681c4d07d   Johannes Berg   mac80211: fix loc...
35
  static struct lock_class_key ieee80211_rx_skb_queue_class;
0d143fe1e   Johannes Berg   mac80211: move re...
36
  void ieee80211_configure_filter(struct ieee80211_local *local)
4150c5721   Johannes Berg   [PATCH] mac80211:...
37
  {
3ac64beec   Johannes Berg   mac80211: allow c...
38
  	u64 mc;
4150c5721   Johannes Berg   [PATCH] mac80211:...
39
40
  	unsigned int changed_flags;
  	unsigned int new_flags = 0;
53918994b   Johannes Berg   [PATCH] mac80211:...
41
  	if (atomic_read(&local->iff_promiscs))
4150c5721   Johannes Berg   [PATCH] mac80211:...
42
  		new_flags |= FIF_PROMISC_IN_BSS;
53918994b   Johannes Berg   [PATCH] mac80211:...
43
  	if (atomic_read(&local->iff_allmultis))
4150c5721   Johannes Berg   [PATCH] mac80211:...
44
  		new_flags |= FIF_ALLMULTI;
3ac64beec   Johannes Berg   mac80211: allow c...
45
  	if (local->monitors || local->scanning)
8cc9a7391   Michael Wu   mac80211: Use mon...
46
  		new_flags |= FIF_BCN_PRBRESP_PROMISC;
7be5086d4   Johannes Berg   mac80211: add pro...
47
48
  	if (local->fif_probe_req || local->probe_req_reg)
  		new_flags |= FIF_PROBE_REQ;
8cc9a7391   Michael Wu   mac80211: Use mon...
49
50
51
52
53
54
55
56
57
58
59
  	if (local->fif_fcsfail)
  		new_flags |= FIF_FCSFAIL;
  
  	if (local->fif_plcpfail)
  		new_flags |= FIF_PLCPFAIL;
  
  	if (local->fif_control)
  		new_flags |= FIF_CONTROL;
  
  	if (local->fif_other_bss)
  		new_flags |= FIF_OTHER_BSS;
4150c5721   Johannes Berg   [PATCH] mac80211:...
60

e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
61
62
  	if (local->fif_pspoll)
  		new_flags |= FIF_PSPOLL;
3ac64beec   Johannes Berg   mac80211: allow c...
63
  	spin_lock_bh(&local->filter_lock);
4150c5721   Johannes Berg   [PATCH] mac80211:...
64
  	changed_flags = local->filter_flags ^ new_flags;
22bedad3c   Jiri Pirko   net: convert mult...
65
  	mc = drv_prepare_multicast(local, &local->mc_list);
3ac64beec   Johannes Berg   mac80211: allow c...
66
  	spin_unlock_bh(&local->filter_lock);
4150c5721   Johannes Berg   [PATCH] mac80211:...
67
68
  	/* be a bit nasty */
  	new_flags |= (1<<31);
3ac64beec   Johannes Berg   mac80211: allow c...
69
  	drv_configure_filter(local, changed_flags, &new_flags, mc);
4150c5721   Johannes Berg   [PATCH] mac80211:...
70
71
72
73
74
  
  	WARN_ON(new_flags & (1<<31));
  
  	local->filter_flags = new_flags & ~(1<<31);
  }
3ac64beec   Johannes Berg   mac80211: allow c...
75
76
77
78
79
80
81
  static void ieee80211_reconfig_filter(struct work_struct *work)
  {
  	struct ieee80211_local *local =
  		container_of(work, struct ieee80211_local, reconfig_filter);
  
  	ieee80211_configure_filter(local);
  }
b23b025fe   Ben Greear   mac80211: Optimiz...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  /*
   * Returns true if we are logically configured to be on
   * the operating channel AND the hardware-conf is currently
   * configured on the operating channel.  Compares channel-type
   * as well.
   */
  bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
  {
  	struct ieee80211_channel *chan, *scan_chan;
  	enum nl80211_channel_type channel_type;
  
  	/* This logic needs to match logic in ieee80211_hw_config */
  	if (local->scan_channel) {
  		chan = local->scan_channel;
4f2e9d91f   Ben Greear   mac80211: Allow s...
96
97
98
99
100
101
102
  		/* If scanning on oper channel, use whatever channel-type
  		 * is currently in use.
  		 */
  		if (chan == local->oper_channel)
  			channel_type = local->_oper_channel_type;
  		else
  			channel_type = NL80211_CHAN_NO_HT;
b23b025fe   Ben Greear   mac80211: Optimiz...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  	} else if (local->tmp_channel) {
  		chan = scan_chan = local->tmp_channel;
  		channel_type = local->tmp_channel_type;
  	} else {
  		chan = local->oper_channel;
  		channel_type = local->_oper_channel_type;
  	}
  
  	if (chan != local->oper_channel ||
  	    channel_type != local->_oper_channel_type)
  		return false;
  
  	/* Check current hardware-config against oper_channel. */
  	if ((local->oper_channel != local->hw.conf.channel) ||
  	    (local->_oper_channel_type != local->hw.conf.channel_type))
  		return false;
  
  	return true;
  }
e8975581f   Johannes Berg   mac80211: introdu...
122
  int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
b2c258fb1   Johannes Berg   [MAC80211]: reord...
123
  {
58905ca5b   Johannes Berg   mac80211: fix sca...
124
  	struct ieee80211_channel *chan, *scan_chan;
b2c258fb1   Johannes Berg   [MAC80211]: reord...
125
  	int ret = 0;
e8975581f   Johannes Berg   mac80211: introdu...
126
  	int power;
094d05dc3   Sujith   mac80211: Fix HT ...
127
  	enum nl80211_channel_type channel_type;
ffd2778bb   Felix Fietkau   mac80211: fix dri...
128
  	u32 offchannel_flag;
f0706e828   Jiri Benc   [MAC80211]: Add m...
129

cb121bad6   Johannes Berg   mac80211: add mig...
130
  	might_sleep();
58905ca5b   Johannes Berg   mac80211: fix sca...
131
  	scan_chan = local->scan_channel;
b23b025fe   Ben Greear   mac80211: Optimiz...
132
133
134
  	/* If this off-channel logic ever changes,  ieee80211_on_oper_channel
  	 * may need to change as well.
  	 */
ffd2778bb   Felix Fietkau   mac80211: fix dri...
135
  	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
58905ca5b   Johannes Berg   mac80211: fix sca...
136
137
  	if (scan_chan) {
  		chan = scan_chan;
4f2e9d91f   Ben Greear   mac80211: Allow s...
138
139
140
141
142
143
144
  		/* If scanning on oper channel, use whatever channel-type
  		 * is currently in use.
  		 */
  		if (chan == local->oper_channel)
  			channel_type = local->_oper_channel_type;
  		else
  			channel_type = NL80211_CHAN_NO_HT;
b23b025fe   Ben Greear   mac80211: Optimiz...
145
  	} else if (local->tmp_channel) {
b8bc4b0aa   Johannes Berg   mac80211: support...
146
147
  		chan = scan_chan = local->tmp_channel;
  		channel_type = local->tmp_channel_type;
72bdcf343   Jouni Malinen   nl80211: Add freq...
148
  	} else {
b2c258fb1   Johannes Berg   [MAC80211]: reord...
149
  		chan = local->oper_channel;
0aaffa9b9   Johannes Berg   mac80211: improve...
150
  		channel_type = local->_oper_channel_type;
72bdcf343   Jouni Malinen   nl80211: Add freq...
151
  	}
b23b025fe   Ben Greear   mac80211: Optimiz...
152
153
154
155
156
157
  
  	if (chan != local->oper_channel ||
  	    channel_type != local->_oper_channel_type)
  		local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
  	else
  		local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
ffd2778bb   Felix Fietkau   mac80211: fix dri...
158
  	offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
f0706e828   Jiri Benc   [MAC80211]: Add m...
159

ffd2778bb   Felix Fietkau   mac80211: fix dri...
160
  	if (offchannel_flag || chan != local->hw.conf.channel ||
4797938c5   Johannes Berg   mac80211: clean u...
161
  	    channel_type != local->hw.conf.channel_type) {
e8975581f   Johannes Berg   mac80211: introdu...
162
  		local->hw.conf.channel = chan;
4797938c5   Johannes Berg   mac80211: clean u...
163
  		local->hw.conf.channel_type = channel_type;
e8975581f   Johannes Berg   mac80211: introdu...
164
165
  		changed |= IEEE80211_CONF_CHANGE_CHANNEL;
  	}
8318d78a4   Johannes Berg   cfg80211 API for ...
166

0f78231bf   Johannes Berg   mac80211: enable ...
167
168
169
170
171
172
173
174
175
176
177
  	if (!conf_is_ht(&local->hw.conf)) {
  		/*
  		 * mac80211.h documents that this is only valid
  		 * when the channel is set to an HT type, and
  		 * that otherwise STATIC is used.
  		 */
  		local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC;
  	} else if (local->hw.conf.smps_mode != local->smps_mode) {
  		local->hw.conf.smps_mode = local->smps_mode;
  		changed |= IEEE80211_CONF_CHANGE_SMPS;
  	}
59bdf3b0f   Ben Greear   mac80211: Ensure ...
178
179
  	if ((local->scanning & SCAN_SW_SCANNING) ||
  	    (local->scanning & SCAN_HW_SCANNING))
e8975581f   Johannes Berg   mac80211: introdu...
180
  		power = chan->max_power;
8318d78a4   Johannes Berg   cfg80211 API for ...
181
  	else
a8302de93   Vasanthakumar Thiagarajan   mac80211: Handle ...
182
183
184
  		power = local->power_constr_level ?
  			(chan->max_power - local->power_constr_level) :
  			chan->max_power;
47afbaf5a   Johannes Berg   mac80211: correct...
185
  	if (local->user_power_level >= 0)
a8302de93   Vasanthakumar Thiagarajan   mac80211: Handle ...
186
  		power = min(power, local->user_power_level);
e8975581f   Johannes Berg   mac80211: introdu...
187
188
189
190
  	if (local->hw.conf.power_level != power) {
  		changed |= IEEE80211_CONF_CHANGE_POWER;
  		local->hw.conf.power_level = power;
  	}
b2c258fb1   Johannes Berg   [MAC80211]: reord...
191

e8975581f   Johannes Berg   mac80211: introdu...
192
  	if (changed && local->open_count) {
244879813   Johannes Berg   mac80211: add dri...
193
  		ret = drv_config(local, changed);
d73782fdd   Johannes Berg   mac80211: clean u...
194
  		/*
447107fb3   Reinette Chatre   mac80211: remove ...
195
  		 * Goal:
d73782fdd   Johannes Berg   mac80211: clean u...
196
197
  		 * HW reconfiguration should never fail, the driver has told
  		 * us what it can support so it should live up to that promise.
447107fb3   Reinette Chatre   mac80211: remove ...
198
199
200
201
202
203
204
205
206
  		 *
  		 * Current status:
  		 * rfkill is not integrated with mac80211 and a
  		 * configuration command can thus fail if hardware rfkill
  		 * is enabled
  		 *
  		 * FIXME: integrate rfkill with mac80211 and then add this
  		 * WARN_ON() back
  		 *
d73782fdd   Johannes Berg   mac80211: clean u...
207
  		 */
447107fb3   Reinette Chatre   mac80211: remove ...
208
  		/* WARN_ON(ret); */
d73782fdd   Johannes Berg   mac80211: clean u...
209
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
210

b2c258fb1   Johannes Berg   [MAC80211]: reord...
211
212
  	return ret;
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
213

471b3efdf   Johannes Berg   mac80211: add uni...
214
215
  void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
  				      u32 changed)
d9430a328   Daniel Drake   [MAC80211]: imple...
216
  {
471b3efdf   Johannes Berg   mac80211: add uni...
217
  	struct ieee80211_local *local = sdata->local;
9cef87379   Johannes Berg   mac80211: fix man...
218
  	static const u8 zero[ETH_ALEN] = { 0 };
471b3efdf   Johannes Berg   mac80211: add uni...
219
220
221
  
  	if (!changed)
  		return;
9cef87379   Johannes Berg   mac80211: fix man...
222
223
224
225
226
227
228
229
230
231
232
  	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
  		/*
  		 * While not associated, claim a BSSID of all-zeroes
  		 * so that drivers don't do any weird things with the
  		 * BSSID at that time.
  		 */
  		if (sdata->vif.bss_conf.assoc)
  			sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
  		else
  			sdata->vif.bss_conf.bssid = zero;
  	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
2d0ddec5b   Johannes Berg   mac80211: unify c...
233
234
  		sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
  	else if (sdata->vif.type == NL80211_IFTYPE_AP)
47846c9b0   Johannes Berg   mac80211: reduce ...
235
  		sdata->vif.bss_conf.bssid = sdata->vif.addr;
1be7fe8de   Bill Jordan   mac80211: fix for...
236
237
  	else if (sdata->vif.type == NL80211_IFTYPE_WDS)
  		sdata->vif.bss_conf.bssid = NULL;
2d0ddec5b   Johannes Berg   mac80211: unify c...
238
  	else if (ieee80211_vif_is_mesh(&sdata->vif)) {
2d0ddec5b   Johannes Berg   mac80211: unify c...
239
240
241
242
243
244
245
246
247
  		sdata->vif.bss_conf.bssid = zero;
  	} else {
  		WARN_ON(1);
  		return;
  	}
  
  	switch (sdata->vif.type) {
  	case NL80211_IFTYPE_AP:
  	case NL80211_IFTYPE_ADHOC:
1be7fe8de   Bill Jordan   mac80211: fix for...
248
  	case NL80211_IFTYPE_WDS:
2d0ddec5b   Johannes Berg   mac80211: unify c...
249
250
251
252
253
254
255
256
257
258
259
  	case NL80211_IFTYPE_MESH_POINT:
  		break;
  	default:
  		/* do not warn to simplify caller in scan.c */
  		changed &= ~BSS_CHANGED_BEACON_ENABLED;
  		if (WARN_ON(changed & BSS_CHANGED_BEACON))
  			return;
  		break;
  	}
  
  	if (changed & BSS_CHANGED_BEACON_ENABLED) {
9607e6b66   Johannes Berg   mac80211: add iee...
260
  		if (local->quiescing || !ieee80211_sdata_running(sdata) ||
b23b025fe   Ben Greear   mac80211: Optimiz...
261
  		    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
2d0ddec5b   Johannes Berg   mac80211: unify c...
262
263
264
265
266
267
268
269
270
  			sdata->vif.bss_conf.enable_beacon = false;
  		} else {
  			/*
  			 * Beacon should be enabled, but AP mode must
  			 * check whether there is a beacon configured.
  			 */
  			switch (sdata->vif.type) {
  			case NL80211_IFTYPE_AP:
  				sdata->vif.bss_conf.enable_beacon =
0379185b6   Johannes Berg   mac80211: annotat...
271
  					!!sdata->u.ap.beacon;
2d0ddec5b   Johannes Berg   mac80211: unify c...
272
273
274
  				break;
  			case NL80211_IFTYPE_ADHOC:
  				sdata->vif.bss_conf.enable_beacon =
0379185b6   Johannes Berg   mac80211: annotat...
275
  					!!sdata->u.ibss.presp;
2d0ddec5b   Johannes Berg   mac80211: unify c...
276
  				break;
7659a193f   Javier Cardona   mac80211: Fix com...
277
  #ifdef CONFIG_MAC80211_MESH
2d0ddec5b   Johannes Berg   mac80211: unify c...
278
  			case NL80211_IFTYPE_MESH_POINT:
29cbe68c5   Johannes Berg   cfg80211/mac80211...
279
280
  				sdata->vif.bss_conf.enable_beacon =
  					!!sdata->u.mesh.mesh_id_len;
2d0ddec5b   Johannes Berg   mac80211: unify c...
281
  				break;
7659a193f   Javier Cardona   mac80211: Fix com...
282
  #endif
2d0ddec5b   Johannes Berg   mac80211: unify c...
283
284
285
286
287
288
289
  			default:
  				/* not reached */
  				WARN_ON(1);
  				break;
  			}
  		}
  	}
12375ef93   Johannes Berg   mac80211: trace i...
290
  	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
d9430a328   Daniel Drake   [MAC80211]: imple...
291
  }
f698d856f   Jasper Bryant-Greene   replace net_devic...
292
  u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
d9430a328   Daniel Drake   [MAC80211]: imple...
293
  {
bda3933a8   Johannes Berg   mac80211: move bs...
294
295
296
  	sdata->vif.bss_conf.use_cts_prot = false;
  	sdata->vif.bss_conf.use_short_preamble = false;
  	sdata->vif.bss_conf.use_short_slot = false;
7a5158ef8   Johannes Berg   mac80211: fix sho...
297
298
299
  	return BSS_CHANGED_ERP_CTS_PROT |
  	       BSS_CHANGED_ERP_PREAMBLE |
  	       BSS_CHANGED_ERP_SLOT;
d9430a328   Daniel Drake   [MAC80211]: imple...
300
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
301
302
303
  static void ieee80211_tasklet_handler(unsigned long data)
  {
  	struct ieee80211_local *local = (struct ieee80211_local *) data;
37fbd9080   Johannes Berg   mac80211: allow o...
304
305
  	struct sta_info *sta, *tmp;
  	struct skb_eosp_msg_data *eosp_data;
f0706e828   Jiri Benc   [MAC80211]: Add m...
306
  	struct sk_buff *skb;
f0706e828   Jiri Benc   [MAC80211]: Add m...
307
308
309
310
311
  
  	while ((skb = skb_dequeue(&local->skb_queue)) ||
  	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
  		switch (skb->pkt_type) {
  		case IEEE80211_RX_MSG:
51fb61e76   Johannes Berg   mac80211: move in...
312
  			/* Clear skb->pkt_type in order to not confuse kernel
f0706e828   Jiri Benc   [MAC80211]: Add m...
313
314
  			 * netstack. */
  			skb->pkt_type = 0;
f1d58c252   Johannes Berg   mac80211: push rx...
315
  			ieee80211_rx(local_to_hw(local), skb);
f0706e828   Jiri Benc   [MAC80211]: Add m...
316
317
  			break;
  		case IEEE80211_TX_STATUS_MSG:
f0706e828   Jiri Benc   [MAC80211]: Add m...
318
  			skb->pkt_type = 0;
e039fa4a4   Johannes Berg   mac80211: move TX...
319
  			ieee80211_tx_status(local_to_hw(local), skb);
f0706e828   Jiri Benc   [MAC80211]: Add m...
320
  			break;
37fbd9080   Johannes Berg   mac80211: allow o...
321
322
323
324
325
326
327
328
329
330
331
332
  		case IEEE80211_EOSP_MSG:
  			eosp_data = (void *)skb->cb;
  			for_each_sta_info(local, eosp_data->sta, sta, tmp) {
  				/* skip wrong virtual interface */
  				if (memcmp(eosp_data->iface,
  					   sta->sdata->vif.addr, ETH_ALEN))
  					continue;
  				clear_sta_flag(sta, WLAN_STA_SP);
  				break;
  			}
  			dev_kfree_skb(skb);
  			break;
f4ea83dd7   Johannes Berg   mac80211: rework ...
333
  		default:
5e3f30899   Larry Finger   mac80211: Print u...
334
335
336
  			WARN(1, "mac80211: Packet is of unknown type %d
  ",
  			     skb->pkt_type);
f0706e828   Jiri Benc   [MAC80211]: Add m...
337
338
339
340
341
  			dev_kfree_skb(skb);
  			break;
  		}
  	}
  }
f2753ddba   Johannes Berg   mac80211: add har...
342
343
344
345
  static void ieee80211_restart_work(struct work_struct *work)
  {
  	struct ieee80211_local *local =
  		container_of(work, struct ieee80211_local, restart_work);
bc86863de   Stanislaw Gruszka   mac80211: perform...
346
347
348
349
  	/* wait for scan work complete */
  	flush_workqueue(local->workqueue);
  
  	mutex_lock(&local->mtx);
79f460ca4   Luciano Coelho   mac80211: add sup...
350
351
  	WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
  	     local->sched_scanning,
bc86863de   Stanislaw Gruszka   mac80211: perform...
352
353
354
  		"%s called with hardware scan in progress
  ", __func__);
  	mutex_unlock(&local->mtx);
f2753ddba   Johannes Berg   mac80211: add har...
355
  	rtnl_lock();
4136c4224   Stanislaw Gruszka   mac80211: assure ...
356
  	ieee80211_scan_cancel(local);
f2753ddba   Johannes Berg   mac80211: add har...
357
358
359
360
361
362
363
  	ieee80211_reconfig(local);
  	rtnl_unlock();
  }
  
  void ieee80211_restart_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
b5878a2dc   Johannes Berg   mac80211: enhance...
364
  	trace_api_restart_hw(local);
b196d031f   Michael Buesch   mac80211: Add log...
365
366
367
  	wiphy_info(hw->wiphy,
  		   "Hardware restart was requested
  ");
18145c693   John W. Linville   mac80211: cancel ...
368
  	/* use this reason, ieee80211_reconfig will unblock it */
f2753ddba   Johannes Berg   mac80211: add har...
369
370
371
372
373
374
  	ieee80211_stop_queues_by_reason(hw,
  		IEEE80211_QUEUE_STOP_REASON_SUSPEND);
  
  	schedule_work(&local->restart_work);
  }
  EXPORT_SYMBOL(ieee80211_restart_hw);
0f78231bf   Johannes Berg   mac80211: enable ...
375
376
377
378
379
380
  static void ieee80211_recalc_smps_work(struct work_struct *work)
  {
  	struct ieee80211_local *local =
  		container_of(work, struct ieee80211_local, recalc_smps);
  
  	mutex_lock(&local->iflist_mtx);
025e6be22   Johannes Berg   mac80211: fix dea...
381
  	ieee80211_recalc_smps(local);
0f78231bf   Johannes Berg   mac80211: enable ...
382
383
  	mutex_unlock(&local->iflist_mtx);
  }
26b36cfef   John W. Linville   mac80211: make AR...
384
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
385
386
387
388
389
390
391
392
393
  static int ieee80211_ifa_changed(struct notifier_block *nb,
  				 unsigned long data, void *arg)
  {
  	struct in_ifaddr *ifa = arg;
  	struct ieee80211_local *local =
  		container_of(nb, struct ieee80211_local,
  			     ifa_notifier);
  	struct net_device *ndev = ifa->ifa_dev->dev;
  	struct wireless_dev *wdev = ndev->ieee80211_ptr;
685429623   Juuso Oikarinen   mac80211: Fix cir...
394
  	struct in_device *idev;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
395
  	struct ieee80211_sub_if_data *sdata;
685429623   Juuso Oikarinen   mac80211: Fix cir...
396
  	struct ieee80211_bss_conf *bss_conf;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
397
  	struct ieee80211_if_managed *ifmgd;
685429623   Juuso Oikarinen   mac80211: Fix cir...
398
  	int c = 0;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
399
400
401
402
403
404
405
  
  	/* Make sure it's our interface that got changed */
  	if (!wdev)
  		return NOTIFY_DONE;
  
  	if (wdev->wiphy != local->hw.wiphy)
  		return NOTIFY_DONE;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
406
  	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
685429623   Juuso Oikarinen   mac80211: Fix cir...
407
  	bss_conf = &sdata->vif.bss_conf;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
408

26a58456b   Johannes Berg   mac80211: switch ...
409
410
  	if (!ieee80211_sdata_running(sdata))
  		return NOTIFY_DONE;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
411
412
413
  	/* ARP filtering is only supported in managed mode */
  	if (sdata->vif.type != NL80211_IFTYPE_STATION)
  		return NOTIFY_DONE;
95ae6b228   Eric Dumazet   ipv4: ip_ptr clea...
414
  	idev = __in_dev_get_rtnl(sdata->dev);
685429623   Juuso Oikarinen   mac80211: Fix cir...
415
416
  	if (!idev)
  		return NOTIFY_DONE;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
417
418
  	ifmgd = &sdata->u.mgd;
  	mutex_lock(&ifmgd->mtx);
685429623   Juuso Oikarinen   mac80211: Fix cir...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
  
  	/* Copy the addresses to the bss_conf list */
  	ifa = idev->ifa_list;
  	while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) {
  		bss_conf->arp_addr_list[c] = ifa->ifa_address;
  		ifa = ifa->ifa_next;
  		c++;
  	}
  
  	/* If not all addresses fit the list, disable filtering */
  	if (ifa) {
  		sdata->arp_filter_state = false;
  		c = 0;
  	} else {
  		sdata->arp_filter_state = true;
  	}
  	bss_conf->arp_addr_cnt = c;
  
  	/* Configure driver only if associated */
  	if (ifmgd->associated) {
  		bss_conf->arp_filter_enabled = sdata->arp_filter_state;
  		ieee80211_bss_info_change_notify(sdata,
  						 BSS_CHANGED_ARP_FILTER);
  	}
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
443
444
445
446
  	mutex_unlock(&ifmgd->mtx);
  
  	return NOTIFY_DONE;
  }
26b36cfef   John W. Linville   mac80211: make AR...
447
  #endif
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
448

4e6cbfd09   John W. Linville   mac80211: support...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
  {
  	struct ieee80211_local *local =
  		container_of(napi, struct ieee80211_local, napi);
  
  	return local->ops->napi_poll(&local->hw, budget);
  }
  
  void ieee80211_napi_schedule(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
  
  	napi_schedule(&local->napi);
  }
  EXPORT_SYMBOL(ieee80211_napi_schedule);
  
  void ieee80211_napi_complete(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
  
  	napi_complete(&local->napi);
  }
  EXPORT_SYMBOL(ieee80211_napi_complete);
2e161f78e   Johannes Berg   cfg80211/mac80211...
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  /* There isn't a lot of sense in it, but you can transmit anything you like */
  static const struct ieee80211_txrx_stypes
  ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
  	[NL80211_IFTYPE_ADHOC] = {
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4),
  	},
  	[NL80211_IFTYPE_STATION] = {
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
  	},
  	[NL80211_IFTYPE_AP] = {
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
  			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
  			BIT(IEEE80211_STYPE_DISASSOC >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
  			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
  			BIT(IEEE80211_STYPE_ACTION >> 4),
  	},
  	[NL80211_IFTYPE_AP_VLAN] = {
  		/* copy AP */
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
  			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
  			BIT(IEEE80211_STYPE_DISASSOC >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
  			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
2ca27bcff   Johannes Berg   mac80211: add p2p...
503
504
505
506
507
508
509
510
511
512
513
514
  			BIT(IEEE80211_STYPE_ACTION >> 4),
  	},
  	[NL80211_IFTYPE_P2P_CLIENT] = {
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
  	},
  	[NL80211_IFTYPE_P2P_GO] = {
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
  			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
2e161f78e   Johannes Berg   cfg80211/mac80211...
515
516
517
518
519
  			BIT(IEEE80211_STYPE_DISASSOC >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
  			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
  			BIT(IEEE80211_STYPE_ACTION >> 4),
  	},
c7108a711   Javier Cardona   mac80211: Send me...
520
521
  	[NL80211_IFTYPE_MESH_POINT] = {
  		.tx = 0xffff,
71839121a   Javier Cardona   mac80211: Let use...
522
523
524
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
  			BIT(IEEE80211_STYPE_DEAUTH >> 4),
c7108a711   Javier Cardona   mac80211: Send me...
525
  	},
2e161f78e   Johannes Berg   cfg80211/mac80211...
526
  };
f0706e828   Jiri Benc   [MAC80211]: Add m...
527
528
529
  struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
  					const struct ieee80211_ops *ops)
  {
f0706e828   Jiri Benc   [MAC80211]: Add m...
530
  	struct ieee80211_local *local;
96f5e66e8   Johannes Berg   mac80211: fix agg...
531
  	int priv_size, i;
f0706e828   Jiri Benc   [MAC80211]: Add m...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  	struct wiphy *wiphy;
  
  	/* Ensure 32-byte alignment of our private data and hw private data.
  	 * We use the wiphy priv data for both our ieee80211_local and for
  	 * the driver's private data
  	 *
  	 * In memory it'll be like this:
  	 *
  	 * +-------------------------+
  	 * | struct wiphy	    |
  	 * +-------------------------+
  	 * | struct ieee80211_local  |
  	 * +-------------------------+
  	 * | driver's private data   |
  	 * +-------------------------+
  	 *
  	 */
1ce8e7b57   Eric Dumazet   net: ALIGN/PTR_AL...
549
  	priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
f0706e828   Jiri Benc   [MAC80211]: Add m...
550
551
552
553
554
  
  	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
  
  	if (!wiphy)
  		return NULL;
2e161f78e   Johannes Berg   cfg80211/mac80211...
555
  	wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
207aba601   Johannes Berg   mac80211: support...
556
  	wiphy->privid = mac80211_wiphy_privid;
9bc383de3   Johannes Berg   cfg80211: introdu...
557
558
  	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
  			WIPHY_FLAG_4ADDR_AP |
f0dc7999b   Jouni Malinen   cfg80211: Remove ...
559
  			WIPHY_FLAG_4ADDR_STATION;
207aba601   Johannes Berg   mac80211: support...
560
561
562
  
  	if (!ops->set_key)
  		wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
18a836599   Johannes Berg   cfg80211: introdu...
563

0c1ad2cac   Johannes Berg   mac80211: proper ...
564
  	wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
f0706e828   Jiri Benc   [MAC80211]: Add m...
565
566
  
  	local = wiphy_priv(wiphy);
de95a54b1   Johannes Berg   mac80211: pass al...
567

f0706e828   Jiri Benc   [MAC80211]: Add m...
568
  	local->hw.wiphy = wiphy;
1ce8e7b57   Eric Dumazet   net: ALIGN/PTR_AL...
569
  	local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
f0706e828   Jiri Benc   [MAC80211]: Add m...
570

4480f15ca   Johannes Berg   [PATCH] mac80211:...
571
  	BUG_ON(!ops->tx);
4150c5721   Johannes Berg   [PATCH] mac80211:...
572
573
  	BUG_ON(!ops->start);
  	BUG_ON(!ops->stop);
4480f15ca   Johannes Berg   [PATCH] mac80211:...
574
575
  	BUG_ON(!ops->config);
  	BUG_ON(!ops->add_interface);
4150c5721   Johannes Berg   [PATCH] mac80211:...
576
577
  	BUG_ON(!ops->remove_interface);
  	BUG_ON(!ops->configure_filter);
f0706e828   Jiri Benc   [MAC80211]: Add m...
578
  	local->ops = ops;
e6a9854b0   Johannes Berg   mac80211/drivers:...
579
580
581
  	/* set up some defaults */
  	local->hw.queues = 1;
  	local->hw.max_rates = 1;
78be49ec2   Helmut Schaa   mac80211: distinc...
582
  	local->hw.max_report_rates = 0;
df6ba5d80   Luciano Coelho   mac80211: add hw ...
583
  	local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
39e68712d   Helmut Schaa   mac80211: Don't u...
584
  	local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
b9a5f8cab   Jouni Malinen   nl80211: Add set/...
585
586
  	local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
  	local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
c428c8920   Johannes Berg   mac80211: default...
587
  	local->user_power_level = -1;
50ae0cf15   Kalle Valo   mac80211: add deb...
588
589
  	local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
  	local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
f0706e828   Jiri Benc   [MAC80211]: Add m...
590

79010420c   Johannes Berg   [PATCH] mac80211:...
591
  	INIT_LIST_HEAD(&local->interfaces);
2f787b0b7   YOSHIFUJI Hideaki / 吉藤英明   mac80211: Ensure ...
592
593
  
  	__hw_addr_init(&local->mc_list);
c771c9d8d   Johannes Berg   mac80211: add int...
594
  	mutex_init(&local->iflist_mtx);
a1699b75a   Johannes Berg   mac80211: unify s...
595
  	mutex_init(&local->mtx);
f0706e828   Jiri Benc   [MAC80211]: Add m...
596

ad0e2b5a0   Johannes Berg   mac80211: simplif...
597
  	mutex_init(&local->key_mtx);
3b8d81e02   Johannes Berg   mac80211: remove ...
598
  	spin_lock_init(&local->filter_lock);
ce7c9111a   Kalle Valo   mac80211: track m...
599
  	spin_lock_init(&local->queue_stop_reason_lock);
681c4d07d   Johannes Berg   mac80211: fix loc...
600
601
602
603
604
605
606
607
608
  	/*
  	 * The rx_skb_queue is only accessed from tasklets,
  	 * but other SKB queues are used from within IRQ
  	 * context. Therefore, this one needs a different
  	 * locking class so our direct, non-irq-safe use of
  	 * the queue's lock doesn't throw lockdep warnings.
  	 */
  	skb_queue_head_init_class(&local->rx_skb_queue,
  				  &ieee80211_rx_skb_queue_class);
24a8fdad3   Christian Lamparter   mac80211: seriali...
609

c2b13452b   Johannes Berg   mac80211: clean u...
610
  	INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
f0706e828   Jiri Benc   [MAC80211]: Add m...
611

af6b63741   Johannes Berg   mac80211: general...
612
  	ieee80211_work_init(local);
f2753ddba   Johannes Berg   mac80211: add har...
613
  	INIT_WORK(&local->restart_work, ieee80211_restart_work);
3ac64beec   Johannes Berg   mac80211: allow c...
614
  	INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
0f78231bf   Johannes Berg   mac80211: enable ...
615
616
  	INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
  	local->smps_mode = IEEE80211_SMPS_OFF;
3ac64beec   Johannes Berg   mac80211: allow c...
617

520eb8207   Kalle Valo   mac80211: impleme...
618
619
620
621
622
623
  	INIT_WORK(&local->dynamic_ps_enable_work,
  		  ieee80211_dynamic_ps_enable_work);
  	INIT_WORK(&local->dynamic_ps_disable_work,
  		  ieee80211_dynamic_ps_disable_work);
  	setup_timer(&local->dynamic_ps_timer,
  		    ieee80211_dynamic_ps_timer, (unsigned long) local);
85a9994a0   Luciano Coelho   cfg80211/mac80211...
624
625
  	INIT_WORK(&local->sched_scan_stopped_work,
  		  ieee80211_sched_scan_stopped_work);
f0706e828   Jiri Benc   [MAC80211]: Add m...
626
  	sta_info_init(local);
a6a67db2b   Johannes Berg   mac80211: refcoun...
627
  	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
2a577d987   Johannes Berg   mac80211: rework ...
628
  		skb_queue_head_init(&local->pending[i]);
a6a67db2b   Johannes Berg   mac80211: refcoun...
629
630
  		atomic_set(&local->agg_queue_stop[i], 0);
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
631
632
  	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
  		     (unsigned long)local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
633
634
635
636
  
  	tasklet_init(&local->tasklet,
  		     ieee80211_tasklet_handler,
  		     (unsigned long) local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
637
638
639
  
  	skb_queue_head_init(&local->skb_queue);
  	skb_queue_head_init(&local->skb_queue_unreliable);
4e6cbfd09   John W. Linville   mac80211: support...
640
641
  	/* init dummy netdev for use w/ NAPI */
  	init_dummy_netdev(&local->napi_dev);
fe67c913f   Johannes Berg   mac80211: make LE...
642
  	ieee80211_led_names(local);
21f835896   Johannes Berg   mac80211: impleme...
643
  	ieee80211_hw_roc_setup(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
644
645
646
647
648
649
650
  	return local_to_hw(local);
  }
  EXPORT_SYMBOL(ieee80211_alloc_hw);
  
  int ieee80211_register_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
7527a782e   Johannes Berg   cfg80211: adverti...
651
  	int result, i;
8318d78a4   Johannes Berg   cfg80211 API for ...
652
  	enum ieee80211_band band;
be4a4b6a5   Johannes Berg   mac80211: improve...
653
  	int channels, max_bitrates;
5ef2d41af   Johannes Berg   mac80211: include...
654
  	bool supp_ht;
25e47c18a   Johannes Berg   cfg80211: add cip...
655
  	static const u32 cipher_suites[] = {
5daa8a8e6   Johannes Berg   mac80211: dont ad...
656
  		/* keep WEP first, it may be removed below */
25e47c18a   Johannes Berg   cfg80211: add cip...
657
658
659
660
661
662
663
664
  		WLAN_CIPHER_SUITE_WEP40,
  		WLAN_CIPHER_SUITE_WEP104,
  		WLAN_CIPHER_SUITE_TKIP,
  		WLAN_CIPHER_SUITE_CCMP,
  
  		/* keep last -- depends on hw flags! */
  		WLAN_CIPHER_SUITE_AES_CMAC
  	};
8318d78a4   Johannes Berg   cfg80211 API for ...
665

38bb3e9da   Larry Finger   mac80211: Fix bui...
666
667
668
669
670
  	if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns)
  #ifdef CONFIG_PM
  	    && (!local->ops->suspend || !local->ops->resume)
  #endif
  	    )
eecc48000   Johannes Berg   mac80211: add bas...
671
  		return -EINVAL;
78be49ec2   Helmut Schaa   mac80211: distinc...
672
673
  	if (hw->max_report_rates == 0)
  		hw->max_report_rates = hw->max_rates;
8318d78a4   Johannes Berg   cfg80211 API for ...
674
675
676
677
678
  	/*
  	 * generic code guarantees at least one band,
  	 * set this very early because much code assumes
  	 * that hw.conf.channel is assigned
  	 */
2a5193119   Johannes Berg   cfg80211/nl80211:...
679
  	channels = 0;
de95a54b1   Johannes Berg   mac80211: pass al...
680
  	max_bitrates = 0;
5ef2d41af   Johannes Berg   mac80211: include...
681
  	supp_ht = false;
8318d78a4   Johannes Berg   cfg80211 API for ...
682
683
684
685
  	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
  		struct ieee80211_supported_band *sband;
  
  		sband = local->hw.wiphy->bands[band];
de95a54b1   Johannes Berg   mac80211: pass al...
686
687
688
  		if (!sband)
  			continue;
  		if (!local->oper_channel) {
8318d78a4   Johannes Berg   cfg80211 API for ...
689
690
  			/* init channel we're on */
  			local->hw.conf.channel =
58905ca5b   Johannes Berg   mac80211: fix sca...
691
692
  			local->oper_channel = &sband->channels[0];
  			local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
8318d78a4   Johannes Berg   cfg80211 API for ...
693
  		}
de95a54b1   Johannes Berg   mac80211: pass al...
694
695
696
697
  		channels += sband->n_channels;
  
  		if (max_bitrates < sband->n_bitrates)
  			max_bitrates = sband->n_bitrates;
5ef2d41af   Johannes Berg   mac80211: include...
698
  		supp_ht = supp_ht || sband->ht_cap.ht_supported;
8318d78a4   Johannes Berg   cfg80211 API for ...
699
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
700

5ba63533b   Johannes Berg   cfg80211: fix ali...
701
702
703
  	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
  				      sizeof(void *) * channels, GFP_KERNEL);
  	if (!local->int_scan_req)
2a5193119   Johannes Berg   cfg80211/nl80211:...
704
  		return -ENOMEM;
c72e8d335   Simon Wunderlich   mac80211: fill ra...
705
706
707
708
709
  	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
  		if (!local->hw.wiphy->bands[band])
  			continue;
  		local->int_scan_req->rates[band] = (u32) -1;
  	}
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
710
  	/* if low-level driver supports AP, we also support VLAN */
7527a782e   Johannes Berg   cfg80211: adverti...
711
712
713
714
  	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
  		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
  		hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
  	}
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
715
716
  
  	/* mac80211 always supports monitor */
7527a782e   Johannes Berg   cfg80211: adverti...
717
718
  	hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
  	hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
8e621fc90   Johannes Berg   mac80211: verify ...
719
720
721
722
723
724
725
726
727
728
729
  	/*
  	 * mac80211 doesn't support more than 1 channel, and also not more
  	 * than one IBSS interface
  	 */
  	for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
  		const struct ieee80211_iface_combination *c;
  		int j;
  
  		c = &hw->wiphy->iface_combinations[i];
  
  		if (c->num_different_channels > 1)
7527a782e   Johannes Berg   cfg80211: adverti...
730
  			return -EINVAL;
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
731

8e621fc90   Johannes Berg   mac80211: verify ...
732
733
734
735
736
  		for (j = 0; j < c->n_limits; j++)
  			if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
  			    c->limits[j].max > 1)
  				return -EINVAL;
  	}
5eb5a52da   Johannes Berg   mac80211: fix mes...
737
738
739
740
  #ifndef CONFIG_MAC80211_MESH
  	/* mesh depends on Kconfig, but drivers should set it if they want */
  	local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
  #endif
1570ca592   Javier Cardona   mac80211: send no...
741
742
743
744
  	/* if the underlying driver supports mesh, mac80211 will (at least)
  	 * provide routing of mesh authentication frames to userspace */
  	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
  		local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
a621fa4d6   Johannes Berg   mac80211: allow c...
745
746
  	/* mac80211 supports control port protocol changing */
  	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
77965c970   Johannes Berg   cfg80211: clean u...
747
748
749
750
  	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
  		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
  	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
  		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
ab13315af   Kalle Valo   mac80211: add U-A...
751
752
753
754
  	WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
  	     && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
  	     "U-APSD not supported with HW_PS_NULLFUNC_STACK
  ");
de95a54b1   Johannes Berg   mac80211: pass al...
755
756
757
  	/*
  	 * Calculate scan IE length -- we need this to alloc
  	 * memory and to subtract from the driver limit. It
dc9f48ce7   Jouni Malinen   mac80211: Fix sca...
758
  	 * includes the DS Params, (extended) supported rates, and HT
de95a54b1   Johannes Berg   mac80211: pass al...
759
760
  	 * information -- SSID is the driver's responsibility.
  	 */
dc9f48ce7   Jouni Malinen   mac80211: Fix sca...
761
762
  	local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
  		3 /* DS Params */;
5ef2d41af   Johannes Berg   mac80211: include...
763
764
  	if (supp_ht)
  		local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
de95a54b1   Johannes Berg   mac80211: pass al...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  
  	if (!local->ops->hw_scan) {
  		/* For hw_scan, driver needs to set these up. */
  		local->hw.wiphy->max_scan_ssids = 4;
  		local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
  	}
  
  	/*
  	 * If the driver supports any scan IEs, then assume the
  	 * limit includes the IEs mac80211 will add, otherwise
  	 * leave it at zero and let the driver sort it out; we
  	 * still pass our IEs to the driver but userspace will
  	 * not be allowed to in that case.
  	 */
  	if (local->hw.wiphy->max_scan_ie_len)
  		local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
3ffc2a905   Johannes Berg   mac80211: allow v...
781
782
783
784
785
786
787
  	/* Set up cipher suites unless driver already did */
  	if (!local->hw.wiphy->cipher_suites) {
  		local->hw.wiphy->cipher_suites = cipher_suites;
  		local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
  		if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
  			local->hw.wiphy->n_cipher_suites--;
  	}
5daa8a8e6   Johannes Berg   mac80211: dont ad...
788
  	if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
3ffc2a905   Johannes Berg   mac80211: allow v...
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
  		if (local->hw.wiphy->cipher_suites == cipher_suites) {
  			local->hw.wiphy->cipher_suites += 2;
  			local->hw.wiphy->n_cipher_suites -= 2;
  		} else {
  			u32 *suites;
  			int r, w = 0;
  
  			/* Filter out WEP */
  
  			suites = kmemdup(
  				local->hw.wiphy->cipher_suites,
  				sizeof(u32) * local->hw.wiphy->n_cipher_suites,
  				GFP_KERNEL);
  			if (!suites)
  				return -ENOMEM;
  			for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
  				u32 suite = local->hw.wiphy->cipher_suites[r];
  				if (suite == WLAN_CIPHER_SUITE_WEP40 ||
  				    suite == WLAN_CIPHER_SUITE_WEP104)
  					continue;
  				suites[w++] = suite;
  			}
  			local->hw.wiphy->cipher_suites = suites;
  			local->hw.wiphy->n_cipher_suites = w;
  			local->wiphy_ciphers_allocated = true;
  		}
5daa8a8e6   Johannes Berg   mac80211: dont ad...
815
  	}
25e47c18a   Johannes Berg   cfg80211: add cip...
816

21f835896   Johannes Berg   mac80211: impleme...
817
818
  	if (!local->ops->remain_on_channel)
  		local->hw.wiphy->max_remain_on_channel_duration = 5000;
a293911d4   Johannes Berg   nl80211: advertis...
819

79f460ca4   Luciano Coelho   mac80211: add sup...
820
821
  	if (local->ops->sched_scan_start)
  		local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
dfe018bf9   Arik Nemtsov   mac80211: handle ...
822
823
824
  	/* mac80211 based drivers don't support internal TDLS setup */
  	if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
  		local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
f0706e828   Jiri Benc   [MAC80211]: Add m...
825
826
  	result = wiphy_register(local->hw.wiphy);
  	if (result < 0)
2a5193119   Johannes Berg   cfg80211/nl80211:...
827
  		goto fail_wiphy_register;
f0706e828   Jiri Benc   [MAC80211]: Add m...
828

e25300836   Johannes Berg   mac80211: use mul...
829
830
831
832
  	/*
  	 * We use the number of queues for feature tests (QoS, HT) internally
  	 * so restrict them appropriately.
  	 */
e25300836   Johannes Berg   mac80211: use mul...
833
834
  	if (hw->queues > IEEE80211_MAX_QUEUES)
  		hw->queues = IEEE80211_MAX_QUEUES;
e25300836   Johannes Berg   mac80211: use mul...
835

42935ecaf   Luis R. Rodriguez   mac80211: redefin...
836
  	local->workqueue =
99b88a0ec   Tejun Heo   mac80211: cancel ...
837
  		alloc_ordered_workqueue(wiphy_name(local->hw.wiphy), 0);
42935ecaf   Luis R. Rodriguez   mac80211: redefin...
838
  	if (!local->workqueue) {
f0706e828   Jiri Benc   [MAC80211]: Add m...
839
840
841
  		result = -ENOMEM;
  		goto fail_workqueue;
  	}
b306f4530   Johannes Berg   [PATCH] mac80211:...
842
843
844
845
846
  	/*
  	 * The hardware needs headroom for sending the frame,
  	 * and we need some headroom for passing the frame to monitor
  	 * interfaces, but never both at the same time.
  	 */
33ccad35a   Jiri Benc   [PATCH] mac80211:...
847
  	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
a2fe81667   Helmut Schaa   mac80211: Build T...
848
  				   IEEE80211_TX_STATUS_HEADROOM);
b306f4530   Johannes Berg   [PATCH] mac80211:...
849

e9f207f0f   Jiri Benc   [MAC80211]: Add d...
850
  	debugfs_hw_add(local);
b446918b7   Helmut Schaa   mac80211: use lis...
851
852
853
854
  	/*
  	 * if the driver doesn't specify a max listen interval we
  	 * use 5 which should be a safe default
  	 */
ea95bba41   Tomas Winkler   mac80211: make li...
855
  	if (local->hw.max_listen_interval == 0)
b446918b7   Helmut Schaa   mac80211: use lis...
856
  		local->hw.max_listen_interval = 5;
ea95bba41   Tomas Winkler   mac80211: make li...
857
858
  
  	local->hw.conf.listen_interval = local->hw.max_listen_interval;
ff6163810   Juuso Oikarinen   mac80211: Fix ps-...
859
  	local->dynamic_ps_forced_timeout = -1;
195e294d2   Juuso Oikarinen   mac80211: Determi...
860

d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
861
  	result = ieee80211_wep_init(local);
3473187d2   John W. Linville   mac80211: remove ...
862
  	if (result < 0)
0fb9a9ec2   Joe Perches   net/mac80211: Use...
863
864
865
  		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d
  ",
  			    result);
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
866

f0706e828   Jiri Benc   [MAC80211]: Add m...
867
  	rtnl_lock();
f0706e828   Jiri Benc   [MAC80211]: Add m...
868

830f90386   Johannes Berg   mac80211: allow d...
869
870
  	result = ieee80211_init_rate_ctrl_alg(local,
  					      hw->rate_control_algorithm);
f0706e828   Jiri Benc   [MAC80211]: Add m...
871
  	if (result < 0) {
0fb9a9ec2   Joe Perches   net/mac80211: Use...
872
873
874
  		wiphy_debug(local->hw.wiphy,
  			    "Failed to initialize rate control algorithm
  ");
f0706e828   Jiri Benc   [MAC80211]: Add m...
875
876
  		goto fail_rate;
  	}
8dffff216   Johannes Berg   mac80211: only cr...
877
878
879
880
881
  	/* add one default STA interface if supported */
  	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
  		result = ieee80211_if_add(local, "wlan%d", NULL,
  					  NL80211_IFTYPE_STATION, NULL);
  		if (result)
0fb9a9ec2   Joe Perches   net/mac80211: Use...
882
883
884
  			wiphy_warn(local->hw.wiphy,
  				   "Failed to add default virtual iface
  ");
8dffff216   Johannes Berg   mac80211: only cr...
885
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
886

f0706e828   Jiri Benc   [MAC80211]: Add m...
887
888
889
  	rtnl_unlock();
  
  	ieee80211_led_init(local);
10f644a47   Johannes Berg   mac80211: disable...
890
891
892
893
  	local->network_latency_notifier.notifier_call =
  		ieee80211_max_network_latency;
  	result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
  				     &local->network_latency_notifier);
10f644a47   Johannes Berg   mac80211: disable...
894
895
896
897
  	if (result) {
  		rtnl_lock();
  		goto fail_pm_qos;
  	}
26b36cfef   John W. Linville   mac80211: make AR...
898
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
899
900
901
902
  	local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
  	result = register_inetaddr_notifier(&local->ifa_notifier);
  	if (result)
  		goto fail_ifa;
26b36cfef   John W. Linville   mac80211: make AR...
903
  #endif
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
904

4e6cbfd09   John W. Linville   mac80211: support...
905
906
  	netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
  			local->hw.napi_weight);
f0706e828   Jiri Benc   [MAC80211]: Add m...
907
  	return 0;
93c08c329   Juuso Oikarinen   mac80211: Fix com...
908
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
909
910
911
912
   fail_ifa:
  	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
  			       &local->network_latency_notifier);
  	rtnl_lock();
93c08c329   Juuso Oikarinen   mac80211: Fix com...
913
  #endif
10f644a47   Johannes Berg   mac80211: disable...
914
915
916
   fail_pm_qos:
  	ieee80211_led_exit(local);
  	ieee80211_remove_interfaces(local);
10f644a47   Johannes Berg   mac80211: disable...
917
   fail_rate:
f0706e828   Jiri Benc   [MAC80211]: Add m...
918
  	rtnl_unlock();
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
919
  	ieee80211_wep_free(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
920
  	sta_info_stop(local);
42935ecaf   Luis R. Rodriguez   mac80211: redefin...
921
  	destroy_workqueue(local->workqueue);
10f644a47   Johannes Berg   mac80211: disable...
922
   fail_workqueue:
f0706e828   Jiri Benc   [MAC80211]: Add m...
923
  	wiphy_unregister(local->hw.wiphy);
10f644a47   Johannes Berg   mac80211: disable...
924
   fail_wiphy_register:
3ffc2a905   Johannes Berg   mac80211: allow v...
925
926
  	if (local->wiphy_ciphers_allocated)
  		kfree(local->hw.wiphy->cipher_suites);
11ba964d4   Johannes Berg   mac80211: fix reg...
927
  	kfree(local->int_scan_req);
f0706e828   Jiri Benc   [MAC80211]: Add m...
928
929
930
  	return result;
  }
  EXPORT_SYMBOL(ieee80211_register_hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
931
932
933
  void ieee80211_unregister_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
934
935
936
  
  	tasklet_kill(&local->tx_pending_tasklet);
  	tasklet_kill(&local->tasklet);
10f644a47   Johannes Berg   mac80211: disable...
937
938
  	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
  			       &local->network_latency_notifier);
26b36cfef   John W. Linville   mac80211: make AR...
939
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
940
  	unregister_inetaddr_notifier(&local->ifa_notifier);
26b36cfef   John W. Linville   mac80211: make AR...
941
  #endif
10f644a47   Johannes Berg   mac80211: disable...
942

f0706e828   Jiri Benc   [MAC80211]: Add m...
943
  	rtnl_lock();
79010420c   Johannes Berg   [PATCH] mac80211:...
944
945
946
947
948
  	/*
  	 * At this point, interface list manipulations are fine
  	 * because the driver cannot be handing us frames any
  	 * more and the tasklet is killed.
  	 */
75636525f   Johannes Berg   mac80211: revamp ...
949
  	ieee80211_remove_interfaces(local);
5b2812e92   Johannes Berg   [PATCH] mac80211:...
950

f0706e828   Jiri Benc   [MAC80211]: Add m...
951
  	rtnl_unlock();
071249b1d   Johannes Berg   mac80211: delete ...
952
953
954
955
956
  	/*
  	 * Now all work items will be gone, but the
  	 * timer might still be armed, so delete it
  	 */
  	del_timer_sync(&local->work_timer);
258086a48   Christian Lamparter   mac80211: cancel ...
957
  	cancel_work_sync(&local->restart_work);
3ac64beec   Johannes Berg   mac80211: allow c...
958
  	cancel_work_sync(&local->reconfig_filter);
f0706e828   Jiri Benc   [MAC80211]: Add m...
959
  	ieee80211_clear_tx_pending(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
960
  	rate_control_deinitialize(local);
f64f9e719   Joe Perches   net: Move && and ...
961
962
  	if (skb_queue_len(&local->skb_queue) ||
  	    skb_queue_len(&local->skb_queue_unreliable))
0fb9a9ec2   Joe Perches   net/mac80211: Use...
963
964
  		wiphy_warn(local->hw.wiphy, "skb_queue not empty
  ");
f0706e828   Jiri Benc   [MAC80211]: Add m...
965
966
  	skb_queue_purge(&local->skb_queue);
  	skb_queue_purge(&local->skb_queue_unreliable);
24a8fdad3   Christian Lamparter   mac80211: seriali...
967
  	skb_queue_purge(&local->rx_skb_queue);
f0706e828   Jiri Benc   [MAC80211]: Add m...
968

42935ecaf   Luis R. Rodriguez   mac80211: redefin...
969
  	destroy_workqueue(local->workqueue);
f0706e828   Jiri Benc   [MAC80211]: Add m...
970
  	wiphy_unregister(local->hw.wiphy);
ecb443355   Stanislaw Gruszka   mac80211: fix sus...
971
  	sta_info_stop(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
972
973
  	ieee80211_wep_free(local);
  	ieee80211_led_exit(local);
5ba63533b   Johannes Berg   cfg80211: fix ali...
974
  	kfree(local->int_scan_req);
f0706e828   Jiri Benc   [MAC80211]: Add m...
975
976
977
978
979
980
  }
  EXPORT_SYMBOL(ieee80211_unregister_hw);
  
  void ieee80211_free_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
c771c9d8d   Johannes Berg   mac80211: add int...
981
  	mutex_destroy(&local->iflist_mtx);
a1699b75a   Johannes Berg   mac80211: unify s...
982
  	mutex_destroy(&local->mtx);
c771c9d8d   Johannes Berg   mac80211: add int...
983

3ffc2a905   Johannes Berg   mac80211: allow v...
984
985
  	if (local->wiphy_ciphers_allocated)
  		kfree(local->hw.wiphy->cipher_suites);
f0706e828   Jiri Benc   [MAC80211]: Add m...
986
987
988
  	wiphy_free(local->hw.wiphy);
  }
  EXPORT_SYMBOL(ieee80211_free_hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
989
990
991
992
  static int __init ieee80211_init(void)
  {
  	struct sk_buff *skb;
  	int ret;
e039fa4a4   Johannes Berg   mac80211: move TX...
993
994
  	BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb));
  	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
c6a1fa12d   Johannes Berg   mac80211: minor c...
995
  		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
f0706e828   Jiri Benc   [MAC80211]: Add m...
996

cccf129f8   Felix Fietkau   mac80211: add the...
997
998
999
  	ret = rc80211_minstrel_init();
  	if (ret)
  		return ret;
ec8aa669b   Felix Fietkau   mac80211: add the...
1000
1001
1002
  	ret = rc80211_minstrel_ht_init();
  	if (ret)
  		goto err_minstrel;
4b475898e   Johannes Berg   mac80211: better ...
1003
  	ret = rc80211_pid_init();
ad0183759   Mattias Nissler   mac80211: add PID...
1004
  	if (ret)
47846c9b0   Johannes Berg   mac80211: reduce ...
1005
  		goto err_pid;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1006

47846c9b0   Johannes Berg   mac80211: reduce ...
1007
1008
1009
  	ret = ieee80211_iface_init();
  	if (ret)
  		goto err_netdev;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
1010

f0706e828   Jiri Benc   [MAC80211]: Add m...
1011
  	return 0;
47846c9b0   Johannes Berg   mac80211: reduce ...
1012
1013
1014
   err_netdev:
  	rc80211_pid_exit();
   err_pid:
ec8aa669b   Felix Fietkau   mac80211: add the...
1015
1016
  	rc80211_minstrel_ht_exit();
   err_minstrel:
47846c9b0   Johannes Berg   mac80211: reduce ...
1017
1018
1019
  	rc80211_minstrel_exit();
  
  	return ret;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1020
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
1021
1022
  static void __exit ieee80211_exit(void)
  {
4b475898e   Johannes Berg   mac80211: better ...
1023
  	rc80211_pid_exit();
ec8aa669b   Felix Fietkau   mac80211: add the...
1024
  	rc80211_minstrel_ht_exit();
cccf129f8   Felix Fietkau   mac80211: add the...
1025
  	rc80211_minstrel_exit();
ac71c691e   Johannes Berg   mac80211: make si...
1026

f7a921443   Luis Carlos Cobo   mac80211: complet...
1027
1028
  	if (mesh_allocated)
  		ieee80211s_stop();
902acc789   Johannes Berg   mac80211: clean u...
1029

47846c9b0   Johannes Berg   mac80211: reduce ...
1030
  	ieee80211_iface_exit();
d07c7cf49   Johannes Berg   mac80211: add mis...
1031
1032
  
  	rcu_barrier();
f0706e828   Jiri Benc   [MAC80211]: Add m...
1033
  }
ca9938fea   Johannes Berg   [PATCH] mac80211:...
1034
  subsys_initcall(ieee80211_init);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1035
1036
1037
1038
  module_exit(ieee80211_exit);
  
  MODULE_DESCRIPTION("IEEE 802.11 subsystem");
  MODULE_LICENSE("GPL");