Blame view

net/mac80211/main.c 29.4 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;
cd6c524e9   Dmitry TARNYAGIN   mac80211: Do not ...
45
  	if (local->monitors || test_bit(SCAN_SW_SCANNING, &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);
  }
e8975581f   Johannes Berg   mac80211: introdu...
82
  int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
b2c258fb1   Johannes Berg   [MAC80211]: reord...
83
  {
5e5202a40   Stanislaw Gruszka   mac80211: remove ...
84
  	struct ieee80211_channel *chan;
b2c258fb1   Johannes Berg   [MAC80211]: reord...
85
  	int ret = 0;
e8975581f   Johannes Berg   mac80211: introdu...
86
  	int power;
094d05dc3   Sujith   mac80211: Fix HT ...
87
  	enum nl80211_channel_type channel_type;
ffd2778bb   Felix Fietkau   mac80211: fix dri...
88
  	u32 offchannel_flag;
f0706e828   Jiri Benc   [MAC80211]: Add m...
89

cb121bad6   Johannes Berg   mac80211: add mig...
90
  	might_sleep();
b23b025fe   Ben Greear   mac80211: Optimiz...
91
92
93
  	/* If this off-channel logic ever changes,  ieee80211_on_oper_channel
  	 * may need to change as well.
  	 */
ffd2778bb   Felix Fietkau   mac80211: fix dri...
94
  	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
5e5202a40   Stanislaw Gruszka   mac80211: remove ...
95
96
  	if (local->scan_channel) {
  		chan = local->scan_channel;
4f2e9d91f   Ben Greear   mac80211: Allow s...
97
98
99
100
101
102
103
  		/* 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...
104
  	} else if (local->tmp_channel) {
5e5202a40   Stanislaw Gruszka   mac80211: remove ...
105
  		chan = local->tmp_channel;
b8bc4b0aa   Johannes Berg   mac80211: support...
106
  		channel_type = local->tmp_channel_type;
72bdcf343   Jouni Malinen   nl80211: Add freq...
107
  	} else {
b2c258fb1   Johannes Berg   [MAC80211]: reord...
108
  		chan = local->oper_channel;
0aaffa9b9   Johannes Berg   mac80211: improve...
109
  		channel_type = local->_oper_channel_type;
72bdcf343   Jouni Malinen   nl80211: Add freq...
110
  	}
b23b025fe   Ben Greear   mac80211: Optimiz...
111
112
113
114
115
116
  
  	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...
117
  	offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
f0706e828   Jiri Benc   [MAC80211]: Add m...
118

ffd2778bb   Felix Fietkau   mac80211: fix dri...
119
  	if (offchannel_flag || chan != local->hw.conf.channel ||
4797938c5   Johannes Berg   mac80211: clean u...
120
  	    channel_type != local->hw.conf.channel_type) {
e8975581f   Johannes Berg   mac80211: introdu...
121
  		local->hw.conf.channel = chan;
4797938c5   Johannes Berg   mac80211: clean u...
122
  		local->hw.conf.channel_type = channel_type;
e8975581f   Johannes Berg   mac80211: introdu...
123
124
  		changed |= IEEE80211_CONF_CHANGE_CHANNEL;
  	}
8318d78a4   Johannes Berg   cfg80211 API for ...
125

0f78231bf   Johannes Berg   mac80211: enable ...
126
127
128
129
130
131
132
133
134
135
136
  	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;
  	}
cd6c524e9   Dmitry TARNYAGIN   mac80211: Do not ...
137
138
  	if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
  	    test_bit(SCAN_HW_SCANNING, &local->scanning))
e8975581f   Johannes Berg   mac80211: introdu...
139
  		power = chan->max_power;
8318d78a4   Johannes Berg   cfg80211 API for ...
140
  	else
a8302de93   Vasanthakumar Thiagarajan   mac80211: Handle ...
141
142
143
  		power = local->power_constr_level ?
  			(chan->max_power - local->power_constr_level) :
  			chan->max_power;
47afbaf5a   Johannes Berg   mac80211: correct...
144
  	if (local->user_power_level >= 0)
a8302de93   Vasanthakumar Thiagarajan   mac80211: Handle ...
145
  		power = min(power, local->user_power_level);
e8975581f   Johannes Berg   mac80211: introdu...
146
147
148
149
  	if (local->hw.conf.power_level != power) {
  		changed |= IEEE80211_CONF_CHANGE_POWER;
  		local->hw.conf.power_level = power;
  	}
b2c258fb1   Johannes Berg   [MAC80211]: reord...
150

e8975581f   Johannes Berg   mac80211: introdu...
151
  	if (changed && local->open_count) {
244879813   Johannes Berg   mac80211: add dri...
152
  		ret = drv_config(local, changed);
d73782fdd   Johannes Berg   mac80211: clean u...
153
  		/*
447107fb3   Reinette Chatre   mac80211: remove ...
154
  		 * Goal:
d73782fdd   Johannes Berg   mac80211: clean u...
155
156
  		 * 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 ...
157
158
159
160
161
162
163
164
165
  		 *
  		 * 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...
166
  		 */
447107fb3   Reinette Chatre   mac80211: remove ...
167
  		/* WARN_ON(ret); */
d73782fdd   Johannes Berg   mac80211: clean u...
168
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
169

b2c258fb1   Johannes Berg   [MAC80211]: reord...
170
171
  	return ret;
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
172

471b3efdf   Johannes Berg   mac80211: add uni...
173
174
  void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
  				      u32 changed)
d9430a328   Daniel Drake   [MAC80211]: imple...
175
  {
471b3efdf   Johannes Berg   mac80211: add uni...
176
  	struct ieee80211_local *local = sdata->local;
9cef87379   Johannes Berg   mac80211: fix man...
177
  	static const u8 zero[ETH_ALEN] = { 0 };
471b3efdf   Johannes Berg   mac80211: add uni...
178
179
180
  
  	if (!changed)
  		return;
9cef87379   Johannes Berg   mac80211: fix man...
181
182
183
184
185
186
187
188
189
190
191
  	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...
192
193
  		sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
  	else if (sdata->vif.type == NL80211_IFTYPE_AP)
47846c9b0   Johannes Berg   mac80211: reduce ...
194
  		sdata->vif.bss_conf.bssid = sdata->vif.addr;
1be7fe8de   Bill Jordan   mac80211: fix for...
195
196
  	else if (sdata->vif.type == NL80211_IFTYPE_WDS)
  		sdata->vif.bss_conf.bssid = NULL;
2d0ddec5b   Johannes Berg   mac80211: unify c...
197
  	else if (ieee80211_vif_is_mesh(&sdata->vif)) {
2d0ddec5b   Johannes Berg   mac80211: unify c...
198
199
200
201
202
203
204
205
206
  		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...
207
  	case NL80211_IFTYPE_WDS:
2d0ddec5b   Johannes Berg   mac80211: unify c...
208
209
210
211
212
213
214
215
216
217
218
  	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...
219
  		if (local->quiescing || !ieee80211_sdata_running(sdata) ||
b23b025fe   Ben Greear   mac80211: Optimiz...
220
  		    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
2d0ddec5b   Johannes Berg   mac80211: unify c...
221
222
223
224
225
226
227
228
229
  			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...
230
  					!!sdata->u.ap.beacon;
2d0ddec5b   Johannes Berg   mac80211: unify c...
231
232
233
  				break;
  			case NL80211_IFTYPE_ADHOC:
  				sdata->vif.bss_conf.enable_beacon =
0379185b6   Johannes Berg   mac80211: annotat...
234
  					!!sdata->u.ibss.presp;
2d0ddec5b   Johannes Berg   mac80211: unify c...
235
  				break;
7659a193f   Javier Cardona   mac80211: Fix com...
236
  #ifdef CONFIG_MAC80211_MESH
2d0ddec5b   Johannes Berg   mac80211: unify c...
237
  			case NL80211_IFTYPE_MESH_POINT:
29cbe68c5   Johannes Berg   cfg80211/mac80211...
238
239
  				sdata->vif.bss_conf.enable_beacon =
  					!!sdata->u.mesh.mesh_id_len;
2d0ddec5b   Johannes Berg   mac80211: unify c...
240
  				break;
7659a193f   Javier Cardona   mac80211: Fix com...
241
  #endif
2d0ddec5b   Johannes Berg   mac80211: unify c...
242
243
244
245
246
247
248
  			default:
  				/* not reached */
  				WARN_ON(1);
  				break;
  			}
  		}
  	}
12375ef93   Johannes Berg   mac80211: trace i...
249
  	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
d9430a328   Daniel Drake   [MAC80211]: imple...
250
  }
f698d856f   Jasper Bryant-Greene   replace net_devic...
251
  u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
d9430a328   Daniel Drake   [MAC80211]: imple...
252
  {
bda3933a8   Johannes Berg   mac80211: move bs...
253
254
255
  	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...
256
257
258
  	return BSS_CHANGED_ERP_CTS_PROT |
  	       BSS_CHANGED_ERP_PREAMBLE |
  	       BSS_CHANGED_ERP_SLOT;
d9430a328   Daniel Drake   [MAC80211]: imple...
259
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
260
261
262
  static void ieee80211_tasklet_handler(unsigned long data)
  {
  	struct ieee80211_local *local = (struct ieee80211_local *) data;
37fbd9080   Johannes Berg   mac80211: allow o...
263
264
  	struct sta_info *sta, *tmp;
  	struct skb_eosp_msg_data *eosp_data;
f0706e828   Jiri Benc   [MAC80211]: Add m...
265
  	struct sk_buff *skb;
f0706e828   Jiri Benc   [MAC80211]: Add m...
266
267
268
269
270
  
  	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...
271
  			/* Clear skb->pkt_type in order to not confuse kernel
f0706e828   Jiri Benc   [MAC80211]: Add m...
272
273
  			 * netstack. */
  			skb->pkt_type = 0;
f1d58c252   Johannes Berg   mac80211: push rx...
274
  			ieee80211_rx(local_to_hw(local), skb);
f0706e828   Jiri Benc   [MAC80211]: Add m...
275
276
  			break;
  		case IEEE80211_TX_STATUS_MSG:
f0706e828   Jiri Benc   [MAC80211]: Add m...
277
  			skb->pkt_type = 0;
e039fa4a4   Johannes Berg   mac80211: move TX...
278
  			ieee80211_tx_status(local_to_hw(local), skb);
f0706e828   Jiri Benc   [MAC80211]: Add m...
279
  			break;
37fbd9080   Johannes Berg   mac80211: allow o...
280
281
282
283
284
285
286
287
288
289
290
291
  		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 ...
292
  		default:
5e3f30899   Larry Finger   mac80211: Print u...
293
294
295
  			WARN(1, "mac80211: Packet is of unknown type %d
  ",
  			     skb->pkt_type);
f0706e828   Jiri Benc   [MAC80211]: Add m...
296
297
298
299
300
  			dev_kfree_skb(skb);
  			break;
  		}
  	}
  }
f2753ddba   Johannes Berg   mac80211: add har...
301
302
303
304
  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...
305
306
307
308
  	/* wait for scan work complete */
  	flush_workqueue(local->workqueue);
  
  	mutex_lock(&local->mtx);
79f460ca4   Luciano Coelho   mac80211: add sup...
309
310
  	WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
  	     local->sched_scanning,
bc86863de   Stanislaw Gruszka   mac80211: perform...
311
312
313
  		"%s called with hardware scan in progress
  ", __func__);
  	mutex_unlock(&local->mtx);
f2753ddba   Johannes Berg   mac80211: add har...
314
  	rtnl_lock();
4136c4224   Stanislaw Gruszka   mac80211: assure ...
315
  	ieee80211_scan_cancel(local);
f2753ddba   Johannes Berg   mac80211: add har...
316
317
318
319
320
321
322
  	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...
323
  	trace_api_restart_hw(local);
b196d031f   Michael Buesch   mac80211: Add log...
324
325
326
  	wiphy_info(hw->wiphy,
  		   "Hardware restart was requested
  ");
18145c693   John W. Linville   mac80211: cancel ...
327
  	/* use this reason, ieee80211_reconfig will unblock it */
f2753ddba   Johannes Berg   mac80211: add har...
328
329
330
331
332
333
  	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 ...
334
335
336
337
338
339
  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...
340
  	ieee80211_recalc_smps(local);
0f78231bf   Johannes Berg   mac80211: enable ...
341
342
  	mutex_unlock(&local->iflist_mtx);
  }
26b36cfef   John W. Linville   mac80211: make AR...
343
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
344
345
346
347
348
349
350
351
352
  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...
353
  	struct in_device *idev;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
354
  	struct ieee80211_sub_if_data *sdata;
685429623   Juuso Oikarinen   mac80211: Fix cir...
355
  	struct ieee80211_bss_conf *bss_conf;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
356
  	struct ieee80211_if_managed *ifmgd;
685429623   Juuso Oikarinen   mac80211: Fix cir...
357
  	int c = 0;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
358
359
360
361
362
363
364
  
  	/* 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...
365
  	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
685429623   Juuso Oikarinen   mac80211: Fix cir...
366
  	bss_conf = &sdata->vif.bss_conf;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
367
368
369
370
  
  	/* 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...
371
  	idev = __in_dev_get_rtnl(sdata->dev);
685429623   Juuso Oikarinen   mac80211: Fix cir...
372
373
  	if (!idev)
  		return NOTIFY_DONE;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
374
375
  	ifmgd = &sdata->u.mgd;
  	mutex_lock(&ifmgd->mtx);
685429623   Juuso Oikarinen   mac80211: Fix cir...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  
  	/* 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;
53d69c399   Eliad Peller   mac80211: don't c...
393
  	/* Configure driver only if associated (which also implies it is up) */
685429623   Juuso Oikarinen   mac80211: Fix cir...
394
395
396
397
398
  	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...
399
400
401
402
  	mutex_unlock(&ifmgd->mtx);
  
  	return NOTIFY_DONE;
  }
26b36cfef   John W. Linville   mac80211: make AR...
403
  #endif
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
404

4e6cbfd09   John W. Linville   mac80211: support...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  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...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  /* 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...
459
460
461
462
463
464
465
466
467
468
469
470
  			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...
471
472
473
474
475
  			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...
476
477
  	[NL80211_IFTYPE_MESH_POINT] = {
  		.tx = 0xffff,
71839121a   Javier Cardona   mac80211: Let use...
478
479
480
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
  			BIT(IEEE80211_STYPE_DEAUTH >> 4),
c7108a711   Javier Cardona   mac80211: Send me...
481
  	},
2e161f78e   Johannes Berg   cfg80211/mac80211...
482
  };
ef96a8420   Ben Greear   mac80211: Support...
483
484
485
486
487
488
489
490
491
492
493
494
  static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
  	.ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR |
  			     IEEE80211_HT_AMPDU_PARM_DENSITY,
  
  	.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
  				IEEE80211_HT_CAP_MAX_AMSDU |
  				IEEE80211_HT_CAP_SGI_40),
  	.mcs = {
  		.rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
  			     0xff, 0xff, 0xff, 0xff, 0xff, },
  	},
  };
f0706e828   Jiri Benc   [MAC80211]: Add m...
495
496
497
  struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
  					const struct ieee80211_ops *ops)
  {
f0706e828   Jiri Benc   [MAC80211]: Add m...
498
  	struct ieee80211_local *local;
96f5e66e8   Johannes Berg   mac80211: fix agg...
499
  	int priv_size, i;
f0706e828   Jiri Benc   [MAC80211]: Add m...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
  	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...
517
  	priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
f0706e828   Jiri Benc   [MAC80211]: Add m...
518
519
520
521
522
  
  	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
  
  	if (!wiphy)
  		return NULL;
2e161f78e   Johannes Berg   cfg80211/mac80211...
523
  	wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
207aba601   Johannes Berg   mac80211: support...
524
  	wiphy->privid = mac80211_wiphy_privid;
9bc383de3   Johannes Berg   cfg80211: introdu...
525
526
  	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
  			WIPHY_FLAG_4ADDR_AP |
ee9719245   Johannes Berg   mac80211: report ...
527
  			WIPHY_FLAG_4ADDR_STATION |
7c4ef7122   Johannes Berg   cfg80211: add fla...
528
529
530
  			WIPHY_FLAG_REPORTS_OBSS |
  			WIPHY_FLAG_OFFCHAN_TX |
  			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
207aba601   Johannes Berg   mac80211: support...
531

13c40c546   Alexander Simon   mac80211: Add HT ...
532
533
  	wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
  			  NL80211_FEATURE_HT_IBSS;
a729cff8a   Johannes Berg   mac80211: impleme...
534

207aba601   Johannes Berg   mac80211: support...
535
536
  	if (!ops->set_key)
  		wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
18a836599   Johannes Berg   cfg80211: introdu...
537

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

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

11127e912   Johannes Berg   mac80211: transmi...
545
  	BUG_ON(!ops->tx && !ops->tx_frags);
4150c5721   Johannes Berg   [PATCH] mac80211:...
546
547
  	BUG_ON(!ops->start);
  	BUG_ON(!ops->stop);
4480f15ca   Johannes Berg   [PATCH] mac80211:...
548
549
  	BUG_ON(!ops->config);
  	BUG_ON(!ops->add_interface);
4150c5721   Johannes Berg   [PATCH] mac80211:...
550
551
  	BUG_ON(!ops->remove_interface);
  	BUG_ON(!ops->configure_filter);
f0706e828   Jiri Benc   [MAC80211]: Add m...
552
  	local->ops = ops;
e6a9854b0   Johannes Berg   mac80211/drivers:...
553
554
555
  	/* set up some defaults */
  	local->hw.queues = 1;
  	local->hw.max_rates = 1;
78be49ec2   Helmut Schaa   mac80211: distinc...
556
  	local->hw.max_report_rates = 0;
df6ba5d80   Luciano Coelho   mac80211: add hw ...
557
  	local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
39e68712d   Helmut Schaa   mac80211: Don't u...
558
  	local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
b9a5f8cab   Jouni Malinen   nl80211: Add set/...
559
560
  	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...
561
  	local->user_power_level = -1;
50ae0cf15   Kalle Valo   mac80211: add deb...
562
563
  	local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
  	local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
ef96a8420   Ben Greear   mac80211: Support...
564
  	wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
f0706e828   Jiri Benc   [MAC80211]: Add m...
565

79010420c   Johannes Berg   [PATCH] mac80211:...
566
  	INIT_LIST_HEAD(&local->interfaces);
2f787b0b7   YOSHIFUJI Hideaki / 吉藤英明   mac80211: Ensure ...
567
568
  
  	__hw_addr_init(&local->mc_list);
c771c9d8d   Johannes Berg   mac80211: add int...
569
  	mutex_init(&local->iflist_mtx);
a1699b75a   Johannes Berg   mac80211: unify s...
570
  	mutex_init(&local->mtx);
f0706e828   Jiri Benc   [MAC80211]: Add m...
571

ad0e2b5a0   Johannes Berg   mac80211: simplif...
572
  	mutex_init(&local->key_mtx);
3b8d81e02   Johannes Berg   mac80211: remove ...
573
  	spin_lock_init(&local->filter_lock);
ce7c9111a   Kalle Valo   mac80211: track m...
574
  	spin_lock_init(&local->queue_stop_reason_lock);
681c4d07d   Johannes Berg   mac80211: fix loc...
575
576
577
578
579
580
581
582
583
  	/*
  	 * 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...
584

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

af6b63741   Johannes Berg   mac80211: general...
587
  	ieee80211_work_init(local);
f2753ddba   Johannes Berg   mac80211: add har...
588
  	INIT_WORK(&local->restart_work, ieee80211_restart_work);
3ac64beec   Johannes Berg   mac80211: allow c...
589
  	INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
0f78231bf   Johannes Berg   mac80211: enable ...
590
591
  	INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
  	local->smps_mode = IEEE80211_SMPS_OFF;
3ac64beec   Johannes Berg   mac80211: allow c...
592

520eb8207   Kalle Valo   mac80211: impleme...
593
594
595
596
597
598
  	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...
599
600
  	INIT_WORK(&local->sched_scan_stopped_work,
  		  ieee80211_sched_scan_stopped_work);
a729cff8a   Johannes Berg   mac80211: impleme...
601
602
603
604
  	spin_lock_init(&local->ack_status_lock);
  	idr_init(&local->ack_status_frames);
  	/* preallocate at least one entry */
  	idr_pre_get(&local->ack_status_frames, GFP_KERNEL);
f0706e828   Jiri Benc   [MAC80211]: Add m...
605
  	sta_info_init(local);
a6a67db2b   Johannes Berg   mac80211: refcoun...
606
  	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
2a577d987   Johannes Berg   mac80211: rework ...
607
  		skb_queue_head_init(&local->pending[i]);
a6a67db2b   Johannes Berg   mac80211: refcoun...
608
609
  		atomic_set(&local->agg_queue_stop[i], 0);
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
610
611
  	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
  		     (unsigned long)local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
612
613
614
615
  
  	tasklet_init(&local->tasklet,
  		     ieee80211_tasklet_handler,
  		     (unsigned long) local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
616
617
618
  
  	skb_queue_head_init(&local->skb_queue);
  	skb_queue_head_init(&local->skb_queue_unreliable);
4e6cbfd09   John W. Linville   mac80211: support...
619
620
  	/* init dummy netdev for use w/ NAPI */
  	init_dummy_netdev(&local->napi_dev);
fe67c913f   Johannes Berg   mac80211: make LE...
621
  	ieee80211_led_names(local);
21f835896   Johannes Berg   mac80211: impleme...
622
  	ieee80211_hw_roc_setup(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
623
624
625
626
627
628
629
  	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...
630
  	int result, i;
8318d78a4   Johannes Berg   cfg80211 API for ...
631
  	enum ieee80211_band band;
be4a4b6a5   Johannes Berg   mac80211: improve...
632
  	int channels, max_bitrates;
5ef2d41af   Johannes Berg   mac80211: include...
633
  	bool supp_ht;
25e47c18a   Johannes Berg   cfg80211: add cip...
634
  	static const u32 cipher_suites[] = {
5daa8a8e6   Johannes Berg   mac80211: dont ad...
635
  		/* keep WEP first, it may be removed below */
25e47c18a   Johannes Berg   cfg80211: add cip...
636
637
638
639
640
641
642
643
  		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 ...
644

38bb3e9da   Larry Finger   mac80211: Fix bui...
645
646
647
648
649
  	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...
650
  		return -EINVAL;
78be49ec2   Helmut Schaa   mac80211: distinc...
651
652
  	if (hw->max_report_rates == 0)
  		hw->max_report_rates = hw->max_rates;
8318d78a4   Johannes Berg   cfg80211 API for ...
653
654
655
656
657
  	/*
  	 * 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:...
658
  	channels = 0;
de95a54b1   Johannes Berg   mac80211: pass al...
659
  	max_bitrates = 0;
5ef2d41af   Johannes Berg   mac80211: include...
660
  	supp_ht = false;
8318d78a4   Johannes Berg   cfg80211 API for ...
661
662
663
664
  	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...
665
666
667
  		if (!sband)
  			continue;
  		if (!local->oper_channel) {
8318d78a4   Johannes Berg   cfg80211 API for ...
668
669
  			/* init channel we're on */
  			local->hw.conf.channel =
58905ca5b   Johannes Berg   mac80211: fix sca...
670
671
  			local->oper_channel = &sband->channels[0];
  			local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
8318d78a4   Johannes Berg   cfg80211 API for ...
672
  		}
de95a54b1   Johannes Berg   mac80211: pass al...
673
674
675
676
  		channels += sband->n_channels;
  
  		if (max_bitrates < sband->n_bitrates)
  			max_bitrates = sband->n_bitrates;
5ef2d41af   Johannes Berg   mac80211: include...
677
  		supp_ht = supp_ht || sband->ht_cap.ht_supported;
8318d78a4   Johannes Berg   cfg80211 API for ...
678
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
679

5ba63533b   Johannes Berg   cfg80211: fix ali...
680
681
682
  	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:...
683
  		return -ENOMEM;
c72e8d335   Simon Wunderlich   mac80211: fill ra...
684
685
686
687
688
  	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...
689
  	/* if low-level driver supports AP, we also support VLAN */
7527a782e   Johannes Berg   cfg80211: adverti...
690
691
692
693
  	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...
694
695
  
  	/* mac80211 always supports monitor */
7527a782e   Johannes Berg   cfg80211: adverti...
696
697
  	hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
  	hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
8e621fc90   Johannes Berg   mac80211: verify ...
698
699
700
701
702
703
704
705
706
707
708
  	/*
  	 * 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...
709
  			return -EINVAL;
f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
710

8e621fc90   Johannes Berg   mac80211: verify ...
711
712
713
714
715
  		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...
716
717
718
719
  #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...
720
721
722
723
  	/* 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...
724
725
  	/* mac80211 supports control port protocol changing */
  	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
77965c970   Johannes Berg   cfg80211: clean u...
726
727
728
729
  	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...
730
731
732
733
  	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...
734
735
736
  	/*
  	 * Calculate scan IE length -- we need this to alloc
  	 * memory and to subtract from the driver limit. It
dc9f48ce7   Jouni Malinen   mac80211: Fix sca...
737
  	 * includes the DS Params, (extended) supported rates, and HT
de95a54b1   Johannes Berg   mac80211: pass al...
738
739
  	 * information -- SSID is the driver's responsibility.
  	 */
dc9f48ce7   Jouni Malinen   mac80211: Fix sca...
740
741
  	local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
  		3 /* DS Params */;
5ef2d41af   Johannes Berg   mac80211: include...
742
743
  	if (supp_ht)
  		local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
de95a54b1   Johannes Berg   mac80211: pass al...
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
  
  	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...
760
761
762
763
764
765
766
  	/* 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...
767
  	if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
3ffc2a905   Johannes Berg   mac80211: allow v...
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  		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...
794
  	}
25e47c18a   Johannes Berg   cfg80211: add cip...
795

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

79f460ca4   Luciano Coelho   mac80211: add sup...
799
800
  	if (local->ops->sched_scan_start)
  		local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
dfe018bf9   Arik Nemtsov   mac80211: handle ...
801
802
803
  	/* 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...
804
805
  	result = wiphy_register(local->hw.wiphy);
  	if (result < 0)
2a5193119   Johannes Berg   cfg80211/nl80211:...
806
  		goto fail_wiphy_register;
f0706e828   Jiri Benc   [MAC80211]: Add m...
807

e25300836   Johannes Berg   mac80211: use mul...
808
809
810
811
  	/*
  	 * We use the number of queues for feature tests (QoS, HT) internally
  	 * so restrict them appropriately.
  	 */
e25300836   Johannes Berg   mac80211: use mul...
812
813
  	if (hw->queues > IEEE80211_MAX_QUEUES)
  		hw->queues = IEEE80211_MAX_QUEUES;
e25300836   Johannes Berg   mac80211: use mul...
814

42935ecaf   Luis R. Rodriguez   mac80211: redefin...
815
  	local->workqueue =
99b88a0ec   Tejun Heo   mac80211: cancel ...
816
  		alloc_ordered_workqueue(wiphy_name(local->hw.wiphy), 0);
42935ecaf   Luis R. Rodriguez   mac80211: redefin...
817
  	if (!local->workqueue) {
f0706e828   Jiri Benc   [MAC80211]: Add m...
818
819
820
  		result = -ENOMEM;
  		goto fail_workqueue;
  	}
b306f4530   Johannes Berg   [PATCH] mac80211:...
821
822
823
824
825
  	/*
  	 * 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:...
826
  	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
a2fe81667   Helmut Schaa   mac80211: Build T...
827
  				   IEEE80211_TX_STATUS_HEADROOM);
b306f4530   Johannes Berg   [PATCH] mac80211:...
828

e9f207f0f   Jiri Benc   [MAC80211]: Add d...
829
  	debugfs_hw_add(local);
b446918b7   Helmut Schaa   mac80211: use lis...
830
831
832
833
  	/*
  	 * 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...
834
  	if (local->hw.max_listen_interval == 0)
b446918b7   Helmut Schaa   mac80211: use lis...
835
  		local->hw.max_listen_interval = 5;
ea95bba41   Tomas Winkler   mac80211: make li...
836
837
  
  	local->hw.conf.listen_interval = local->hw.max_listen_interval;
ff6163810   Juuso Oikarinen   mac80211: Fix ps-...
838
  	local->dynamic_ps_forced_timeout = -1;
195e294d2   Juuso Oikarinen   mac80211: Determi...
839

d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
840
  	result = ieee80211_wep_init(local);
3473187d2   John W. Linville   mac80211: remove ...
841
  	if (result < 0)
0fb9a9ec2   Joe Perches   net/mac80211: Use...
842
843
844
  		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d
  ",
  			    result);
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
845

f0706e828   Jiri Benc   [MAC80211]: Add m...
846
  	rtnl_lock();
f0706e828   Jiri Benc   [MAC80211]: Add m...
847

830f90386   Johannes Berg   mac80211: allow d...
848
849
  	result = ieee80211_init_rate_ctrl_alg(local,
  					      hw->rate_control_algorithm);
f0706e828   Jiri Benc   [MAC80211]: Add m...
850
  	if (result < 0) {
0fb9a9ec2   Joe Perches   net/mac80211: Use...
851
852
853
  		wiphy_debug(local->hw.wiphy,
  			    "Failed to initialize rate control algorithm
  ");
f0706e828   Jiri Benc   [MAC80211]: Add m...
854
855
  		goto fail_rate;
  	}
8dffff216   Johannes Berg   mac80211: only cr...
856
857
858
859
860
  	/* 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...
861
862
863
  			wiphy_warn(local->hw.wiphy,
  				   "Failed to add default virtual iface
  ");
8dffff216   Johannes Berg   mac80211: only cr...
864
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
865

f0706e828   Jiri Benc   [MAC80211]: Add m...
866
867
868
  	rtnl_unlock();
  
  	ieee80211_led_init(local);
10f644a47   Johannes Berg   mac80211: disable...
869
870
871
872
  	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...
873
874
875
876
  	if (result) {
  		rtnl_lock();
  		goto fail_pm_qos;
  	}
26b36cfef   John W. Linville   mac80211: make AR...
877
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
878
879
880
881
  	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...
882
  #endif
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
883

4e6cbfd09   John W. Linville   mac80211: support...
884
885
  	netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
  			local->hw.napi_weight);
f0706e828   Jiri Benc   [MAC80211]: Add m...
886
  	return 0;
93c08c329   Juuso Oikarinen   mac80211: Fix com...
887
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
888
889
890
891
   fail_ifa:
  	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
  			       &local->network_latency_notifier);
  	rtnl_lock();
93c08c329   Juuso Oikarinen   mac80211: Fix com...
892
  #endif
10f644a47   Johannes Berg   mac80211: disable...
893
894
895
   fail_pm_qos:
  	ieee80211_led_exit(local);
  	ieee80211_remove_interfaces(local);
10f644a47   Johannes Berg   mac80211: disable...
896
   fail_rate:
f0706e828   Jiri Benc   [MAC80211]: Add m...
897
  	rtnl_unlock();
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
898
  	ieee80211_wep_free(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
899
  	sta_info_stop(local);
42935ecaf   Luis R. Rodriguez   mac80211: redefin...
900
  	destroy_workqueue(local->workqueue);
10f644a47   Johannes Berg   mac80211: disable...
901
   fail_workqueue:
f0706e828   Jiri Benc   [MAC80211]: Add m...
902
  	wiphy_unregister(local->hw.wiphy);
10f644a47   Johannes Berg   mac80211: disable...
903
   fail_wiphy_register:
3ffc2a905   Johannes Berg   mac80211: allow v...
904
905
  	if (local->wiphy_ciphers_allocated)
  		kfree(local->hw.wiphy->cipher_suites);
11ba964d4   Johannes Berg   mac80211: fix reg...
906
  	kfree(local->int_scan_req);
f0706e828   Jiri Benc   [MAC80211]: Add m...
907
908
909
  	return result;
  }
  EXPORT_SYMBOL(ieee80211_register_hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
910
911
912
  void ieee80211_unregister_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
913
914
915
  
  	tasklet_kill(&local->tx_pending_tasklet);
  	tasklet_kill(&local->tasklet);
10f644a47   Johannes Berg   mac80211: disable...
916
917
  	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
  			       &local->network_latency_notifier);
26b36cfef   John W. Linville   mac80211: make AR...
918
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
919
  	unregister_inetaddr_notifier(&local->ifa_notifier);
26b36cfef   John W. Linville   mac80211: make AR...
920
  #endif
10f644a47   Johannes Berg   mac80211: disable...
921

f0706e828   Jiri Benc   [MAC80211]: Add m...
922
  	rtnl_lock();
79010420c   Johannes Berg   [PATCH] mac80211:...
923
924
925
926
927
  	/*
  	 * 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 ...
928
  	ieee80211_remove_interfaces(local);
5b2812e92   Johannes Berg   [PATCH] mac80211:...
929

f0706e828   Jiri Benc   [MAC80211]: Add m...
930
  	rtnl_unlock();
071249b1d   Johannes Berg   mac80211: delete ...
931
932
933
934
935
  	/*
  	 * 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 ...
936
  	cancel_work_sync(&local->restart_work);
3ac64beec   Johannes Berg   mac80211: allow c...
937
  	cancel_work_sync(&local->reconfig_filter);
f0706e828   Jiri Benc   [MAC80211]: Add m...
938
  	ieee80211_clear_tx_pending(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
939
  	rate_control_deinitialize(local);
f64f9e719   Joe Perches   net: Move && and ...
940
941
  	if (skb_queue_len(&local->skb_queue) ||
  	    skb_queue_len(&local->skb_queue_unreliable))
0fb9a9ec2   Joe Perches   net/mac80211: Use...
942
943
  		wiphy_warn(local->hw.wiphy, "skb_queue not empty
  ");
f0706e828   Jiri Benc   [MAC80211]: Add m...
944
945
  	skb_queue_purge(&local->skb_queue);
  	skb_queue_purge(&local->skb_queue_unreliable);
24a8fdad3   Christian Lamparter   mac80211: seriali...
946
  	skb_queue_purge(&local->rx_skb_queue);
f0706e828   Jiri Benc   [MAC80211]: Add m...
947

42935ecaf   Luis R. Rodriguez   mac80211: redefin...
948
  	destroy_workqueue(local->workqueue);
f0706e828   Jiri Benc   [MAC80211]: Add m...
949
  	wiphy_unregister(local->hw.wiphy);
ecb443355   Stanislaw Gruszka   mac80211: fix sus...
950
  	sta_info_stop(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
951
952
  	ieee80211_wep_free(local);
  	ieee80211_led_exit(local);
5ba63533b   Johannes Berg   cfg80211: fix ali...
953
  	kfree(local->int_scan_req);
f0706e828   Jiri Benc   [MAC80211]: Add m...
954
955
  }
  EXPORT_SYMBOL(ieee80211_unregister_hw);
a729cff8a   Johannes Berg   mac80211: impleme...
956
957
958
959
960
961
962
  static int ieee80211_free_ack_frame(int id, void *p, void *data)
  {
  	WARN_ONCE(1, "Have pending ack frames!
  ");
  	kfree_skb(p);
  	return 0;
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
963
964
965
  void ieee80211_free_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
c771c9d8d   Johannes Berg   mac80211: add int...
966
  	mutex_destroy(&local->iflist_mtx);
a1699b75a   Johannes Berg   mac80211: unify s...
967
  	mutex_destroy(&local->mtx);
c771c9d8d   Johannes Berg   mac80211: add int...
968

3ffc2a905   Johannes Berg   mac80211: allow v...
969
970
  	if (local->wiphy_ciphers_allocated)
  		kfree(local->hw.wiphy->cipher_suites);
a729cff8a   Johannes Berg   mac80211: impleme...
971
972
973
  	idr_for_each(&local->ack_status_frames,
  		     ieee80211_free_ack_frame, NULL);
  	idr_destroy(&local->ack_status_frames);
f0706e828   Jiri Benc   [MAC80211]: Add m...
974
975
976
  	wiphy_free(local->hw.wiphy);
  }
  EXPORT_SYMBOL(ieee80211_free_hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
977
978
979
980
  static int __init ieee80211_init(void)
  {
  	struct sk_buff *skb;
  	int ret;
e039fa4a4   Johannes Berg   mac80211: move TX...
981
982
  	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...
983
  		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
f0706e828   Jiri Benc   [MAC80211]: Add m...
984

cccf129f8   Felix Fietkau   mac80211: add the...
985
986
987
  	ret = rc80211_minstrel_init();
  	if (ret)
  		return ret;
ec8aa669b   Felix Fietkau   mac80211: add the...
988
989
990
  	ret = rc80211_minstrel_ht_init();
  	if (ret)
  		goto err_minstrel;
4b475898e   Johannes Berg   mac80211: better ...
991
  	ret = rc80211_pid_init();
ad0183759   Mattias Nissler   mac80211: add PID...
992
  	if (ret)
47846c9b0   Johannes Berg   mac80211: reduce ...
993
  		goto err_pid;
f0706e828   Jiri Benc   [MAC80211]: Add m...
994

47846c9b0   Johannes Berg   mac80211: reduce ...
995
996
997
  	ret = ieee80211_iface_init();
  	if (ret)
  		goto err_netdev;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
998

f0706e828   Jiri Benc   [MAC80211]: Add m...
999
  	return 0;
47846c9b0   Johannes Berg   mac80211: reduce ...
1000
1001
1002
   err_netdev:
  	rc80211_pid_exit();
   err_pid:
ec8aa669b   Felix Fietkau   mac80211: add the...
1003
1004
  	rc80211_minstrel_ht_exit();
   err_minstrel:
47846c9b0   Johannes Berg   mac80211: reduce ...
1005
1006
1007
  	rc80211_minstrel_exit();
  
  	return ret;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1008
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
1009
1010
  static void __exit ieee80211_exit(void)
  {
4b475898e   Johannes Berg   mac80211: better ...
1011
  	rc80211_pid_exit();
ec8aa669b   Felix Fietkau   mac80211: add the...
1012
  	rc80211_minstrel_ht_exit();
cccf129f8   Felix Fietkau   mac80211: add the...
1013
  	rc80211_minstrel_exit();
ac71c691e   Johannes Berg   mac80211: make si...
1014

f7a921443   Luis Carlos Cobo   mac80211: complet...
1015
1016
  	if (mesh_allocated)
  		ieee80211s_stop();
902acc789   Johannes Berg   mac80211: clean u...
1017

47846c9b0   Johannes Berg   mac80211: reduce ...
1018
  	ieee80211_iface_exit();
d07c7cf49   Johannes Berg   mac80211: add mis...
1019
1020
  
  	rcu_barrier();
f0706e828   Jiri Benc   [MAC80211]: Add m...
1021
  }
ca9938fea   Johannes Berg   [PATCH] mac80211:...
1022
  subsys_initcall(ieee80211_init);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1023
1024
1025
1026
  module_exit(ieee80211_exit);
  
  MODULE_DESCRIPTION("IEEE 802.11 subsystem");
  MODULE_LICENSE("GPL");