Blame view

net/mac80211/main.c 35.7 KB
f0706e828   Jiri Benc   [MAC80211]: Add m...
1
2
3
4
  /*
   * Copyright 2002-2005, Instant802 Networks, Inc.
   * Copyright 2005-2006, Devicescape Software, Inc.
   * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
d98ad83ee   Johannes Berg   mac80211: add Int...
5
   * Copyright 2013-2014  Intel Mobile Communications GmbH
f0706e828   Jiri Benc   [MAC80211]: Add m...
6
7
8
9
10
11
12
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  #include <net/mac80211.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
13
14
15
16
17
18
19
20
  #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...
21
  #include <linux/rtnetlink.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
22
  #include <linux/bitmap.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>
a65240c10   Johannes Berg   mac80211: allow d...
26
  #include <net/addrconf.h>
f0706e828   Jiri Benc   [MAC80211]: Add m...
27

f0706e828   Jiri Benc   [MAC80211]: Add m...
28
  #include "ieee80211_i.h"
244879813   Johannes Berg   mac80211: add dri...
29
  #include "driver-ops.h"
2c8dccc77   Johannes Berg   mac80211: rename ...
30
  #include "rate.h"
f7a921443   Luis Carlos Cobo   mac80211: complet...
31
  #include "mesh.h"
f0706e828   Jiri Benc   [MAC80211]: Add m...
32
  #include "wep.h"
2c8dccc77   Johannes Berg   mac80211: rename ...
33
  #include "led.h"
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
34
  #include "debugfs.h"
f0706e828   Jiri Benc   [MAC80211]: Add m...
35

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_allmultis))
4150c5721   Johannes Berg   [PATCH] mac80211:...
42
  		new_flags |= FIF_ALLMULTI;
8a690674e   Ben Greear   mac80211: Support...
43
44
  	if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning) ||
  	    test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning))
8cc9a7391   Michael Wu   mac80211: Use mon...
45
  		new_flags |= FIF_BCN_PRBRESP_PROMISC;
7be5086d4   Johannes Berg   mac80211: add pro...
46
47
  	if (local->fif_probe_req || local->probe_req_reg)
  		new_flags |= FIF_PROBE_REQ;
8cc9a7391   Michael Wu   mac80211: Use mon...
48
49
50
51
52
53
54
55
56
57
58
  	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:...
59

e3b90ca28   Igor Perminov   mac80211: FIF_PSP...
60
61
  	if (local->fif_pspoll)
  		new_flags |= FIF_PSPOLL;
3ac64beec   Johannes Berg   mac80211: allow c...
62
  	spin_lock_bh(&local->filter_lock);
4150c5721   Johannes Berg   [PATCH] mac80211:...
63
  	changed_flags = local->filter_flags ^ new_flags;
22bedad3c   Jiri Pirko   net: convert mult...
64
  	mc = drv_prepare_multicast(local, &local->mc_list);
3ac64beec   Johannes Berg   mac80211: allow c...
65
  	spin_unlock_bh(&local->filter_lock);
4150c5721   Johannes Berg   [PATCH] mac80211:...
66
67
  	/* be a bit nasty */
  	new_flags |= (1<<31);
3ac64beec   Johannes Berg   mac80211: allow c...
68
  	drv_configure_filter(local, changed_flags, &new_flags, mc);
4150c5721   Johannes Berg   [PATCH] mac80211:...
69
70
71
72
73
  
  	WARN_ON(new_flags & (1<<31));
  
  	local->filter_flags = new_flags & ~(1<<31);
  }
3ac64beec   Johannes Berg   mac80211: allow c...
74
75
76
77
78
79
80
  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);
  }
55de908ab   Johannes Berg   mac80211: use cha...
81
  static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
b2c258fb1   Johannes Berg   [MAC80211]: reord...
82
  {
1ea6f9c0d   Johannes Berg   mac80211: handle ...
83
  	struct ieee80211_sub_if_data *sdata;
675a0b049   Karl Beldan   mac80211: Use a c...
84
  	struct cfg80211_chan_def chandef = {};
55de908ab   Johannes Berg   mac80211: use cha...
85
  	u32 changed = 0;
e8975581f   Johannes Berg   mac80211: introdu...
86
  	int power;
ffd2778bb   Felix Fietkau   mac80211: fix dri...
87
  	u32 offchannel_flag;
f0706e828   Jiri Benc   [MAC80211]: Add m...
88

ffd2778bb   Felix Fietkau   mac80211: fix dri...
89
  	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
675a0b049   Karl Beldan   mac80211: Use a c...
90

7ca15a0ae   Simon Wunderlich   mac80211: allow s...
91
92
  	if (local->scan_chandef.chan) {
  		chandef = local->scan_chandef;
b23b025fe   Ben Greear   mac80211: Optimiz...
93
  	} else if (local->tmp_channel) {
675a0b049   Karl Beldan   mac80211: Use a c...
94
95
96
97
98
99
100
101
102
103
104
105
  		chandef.chan = local->tmp_channel;
  		chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
  		chandef.center_freq1 = chandef.chan->center_freq;
  	} else
  		chandef = local->_oper_chandef;
  
  	WARN(!cfg80211_chandef_valid(&chandef),
  	     "control:%d MHz width:%d center: %d/%d MHz",
  	     chandef.chan->center_freq, chandef.width,
  	     chandef.center_freq1, chandef.center_freq2);
  
  	if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
b23b025fe   Ben Greear   mac80211: Optimiz...
106
107
108
  		local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
  	else
  		local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
ffd2778bb   Felix Fietkau   mac80211: fix dri...
109
  	offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
f0706e828   Jiri Benc   [MAC80211]: Add m...
110

675a0b049   Karl Beldan   mac80211: Use a c...
111
112
113
114
  	if (offchannel_flag ||
  	    !cfg80211_chandef_identical(&local->hw.conf.chandef,
  					&local->_oper_chandef)) {
  		local->hw.conf.chandef = chandef;
e8975581f   Johannes Berg   mac80211: introdu...
115
116
  		changed |= IEEE80211_CONF_CHANGE_CHANNEL;
  	}
8318d78a4   Johannes Berg   cfg80211 API for ...
117

0f78231bf   Johannes Berg   mac80211: enable ...
118
119
120
121
122
123
124
125
126
127
128
  	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;
  	}
0430c8834   Simon Wunderlich   cfg80211/mac80211...
129
  	power = ieee80211_chandef_max_power(&chandef);
a8302de93   Vasanthakumar Thiagarajan   mac80211: Handle ...
130

1ea6f9c0d   Johannes Berg   mac80211: handle ...
131
132
133
134
  	rcu_read_lock();
  	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
  		if (!rcu_access_pointer(sdata->vif.chanctx_conf))
  			continue;
764152ff6   Felix Fietkau   mac80211: exclude...
135
136
  		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
  			continue;
1ea6f9c0d   Johannes Berg   mac80211: handle ...
137
138
139
  		power = min(power, sdata->vif.bss_conf.txpower);
  	}
  	rcu_read_unlock();
a8302de93   Vasanthakumar Thiagarajan   mac80211: Handle ...
140

e8975581f   Johannes Berg   mac80211: introdu...
141
142
143
144
  	if (local->hw.conf.power_level != power) {
  		changed |= IEEE80211_CONF_CHANGE_POWER;
  		local->hw.conf.power_level = power;
  	}
b2c258fb1   Johannes Berg   [MAC80211]: reord...
145

55de908ab   Johannes Berg   mac80211: use cha...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  	return changed;
  }
  
  int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
  {
  	int ret = 0;
  
  	might_sleep();
  
  	if (!local->use_chanctx)
  		changed |= ieee80211_hw_conf_chan(local);
  	else
  		changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL |
  			     IEEE80211_CONF_CHANGE_POWER);
e8975581f   Johannes Berg   mac80211: introdu...
160
  	if (changed && local->open_count) {
244879813   Johannes Berg   mac80211: add dri...
161
  		ret = drv_config(local, changed);
d73782fdd   Johannes Berg   mac80211: clean u...
162
  		/*
447107fb3   Reinette Chatre   mac80211: remove ...
163
  		 * Goal:
d73782fdd   Johannes Berg   mac80211: clean u...
164
165
  		 * 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 ...
166
167
168
169
170
171
172
173
174
  		 *
  		 * 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...
175
  		 */
447107fb3   Reinette Chatre   mac80211: remove ...
176
  		/* WARN_ON(ret); */
d73782fdd   Johannes Berg   mac80211: clean u...
177
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
178

b2c258fb1   Johannes Berg   [MAC80211]: reord...
179
180
  	return ret;
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
181

471b3efdf   Johannes Berg   mac80211: add uni...
182
183
  void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
  				      u32 changed)
d9430a328   Daniel Drake   [MAC80211]: imple...
184
  {
471b3efdf   Johannes Berg   mac80211: add uni...
185
  	struct ieee80211_local *local = sdata->local;
990baec02   Felix Fietkau   mac80211: suppres...
186
  	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
471b3efdf   Johannes Berg   mac80211: add uni...
187
  		return;
12375ef93   Johannes Berg   mac80211: trace i...
188
  	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
d9430a328   Daniel Drake   [MAC80211]: imple...
189
  }
f698d856f   Jasper Bryant-Greene   replace net_devic...
190
  u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
d9430a328   Daniel Drake   [MAC80211]: imple...
191
  {
bda3933a8   Johannes Berg   mac80211: move bs...
192
193
194
  	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...
195
196
197
  	return BSS_CHANGED_ERP_CTS_PROT |
  	       BSS_CHANGED_ERP_PREAMBLE |
  	       BSS_CHANGED_ERP_SLOT;
d9430a328   Daniel Drake   [MAC80211]: imple...
198
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
199
200
201
202
  static void ieee80211_tasklet_handler(unsigned long data)
  {
  	struct ieee80211_local *local = (struct ieee80211_local *) data;
  	struct sk_buff *skb;
f0706e828   Jiri Benc   [MAC80211]: Add m...
203
204
205
206
207
  
  	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...
208
  			/* Clear skb->pkt_type in order to not confuse kernel
f0706e828   Jiri Benc   [MAC80211]: Add m...
209
210
  			 * netstack. */
  			skb->pkt_type = 0;
005e472b4   Johannes Berg   mac80211: remove ...
211
  			ieee80211_rx(&local->hw, skb);
f0706e828   Jiri Benc   [MAC80211]: Add m...
212
213
  			break;
  		case IEEE80211_TX_STATUS_MSG:
f0706e828   Jiri Benc   [MAC80211]: Add m...
214
  			skb->pkt_type = 0;
005e472b4   Johannes Berg   mac80211: remove ...
215
  			ieee80211_tx_status(&local->hw, skb);
f0706e828   Jiri Benc   [MAC80211]: Add m...
216
  			break;
f4ea83dd7   Johannes Berg   mac80211: rework ...
217
  		default:
5e3f30899   Larry Finger   mac80211: Print u...
218
219
220
  			WARN(1, "mac80211: Packet is of unknown type %d
  ",
  			     skb->pkt_type);
f0706e828   Jiri Benc   [MAC80211]: Add m...
221
222
223
224
225
  			dev_kfree_skb(skb);
  			break;
  		}
  	}
  }
f2753ddba   Johannes Berg   mac80211: add har...
226
227
228
229
  static void ieee80211_restart_work(struct work_struct *work)
  {
  	struct ieee80211_local *local =
  		container_of(work, struct ieee80211_local, restart_work);
ab499db80   Michal Kazior   mac80211: prevent...
230
  	struct ieee80211_sub_if_data *sdata;
f2753ddba   Johannes Berg   mac80211: add har...
231

bc86863de   Stanislaw Gruszka   mac80211: perform...
232
233
  	/* wait for scan work complete */
  	flush_workqueue(local->workqueue);
2bc533bd9   Eliad Peller   mac80211: handle ...
234
  	flush_work(&local->sched_scan_stopped_work);
bc86863de   Stanislaw Gruszka   mac80211: perform...
235

d43c6b6e6   David Spinadel   mac80211: resched...
236
237
238
  	WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
  	     "%s called with hardware scan in progress
  ", __func__);
bc86863de   Stanislaw Gruszka   mac80211: perform...
239

4a1990682   Johannes Berg   mac80211: disenta...
240
  	flush_work(&local->radar_detected_work);
f2753ddba   Johannes Berg   mac80211: add har...
241
  	rtnl_lock();
37cdc7e35   Emmanuel Grumbach   mac80211: fix a r...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  	list_for_each_entry(sdata, &local->interfaces, list) {
  		/*
  		 * XXX: there may be more work for other vif types and even
  		 * for station mode: a good thing would be to run most of
  		 * the iface type's dependent _stop (ieee80211_mg_stop,
  		 * ieee80211_ibss_stop) etc...
  		 * For now, fix only the specific bug that was seen: race
  		 * between csa_connection_drop_work and us.
  		 */
  		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
  			/*
  			 * This worker is scheduled from the iface worker that
  			 * runs on mac80211's workqueue, so we can't be
  			 * scheduling this worker after the cancel right here.
  			 * The exception is ieee80211_chswitch_done.
  			 * Then we can have a race...
  			 */
  			cancel_work_sync(&sdata->u.mgd.csa_connection_drop_work);
  		}
ab499db80   Michal Kazior   mac80211: prevent...
261
  		flush_delayed_work(&sdata->dec_tailroom_needed_wk);
37cdc7e35   Emmanuel Grumbach   mac80211: fix a r...
262
  	}
4136c4224   Stanislaw Gruszka   mac80211: assure ...
263
  	ieee80211_scan_cancel(local);
470f4d613   Eliad Peller   mac80211: avoid R...
264
265
266
267
  
  	/* make sure any new ROC will consider local->in_reconfig */
  	flush_delayed_work(&local->roc_work);
  	flush_work(&local->hw_roc_done);
f2753ddba   Johannes Berg   mac80211: add har...
268
269
270
271
272
273
274
  	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...
275
  	trace_api_restart_hw(local);
b196d031f   Michael Buesch   mac80211: Add log...
276
277
278
  	wiphy_info(hw->wiphy,
  		   "Hardware restart was requested
  ");
18145c693   John W. Linville   mac80211: cancel ...
279
  	/* use this reason, ieee80211_reconfig will unblock it */
445ea4e83   Johannes Berg   mac80211: stop qu...
280
  	ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
cca07b00a   Luciano Coelho   mac80211: introdu...
281
282
  					IEEE80211_QUEUE_STOP_REASON_SUSPEND,
  					false);
f2753ddba   Johannes Berg   mac80211: add har...
283

04800ada2   Arik Nemtsov   mac80211: stop Rx...
284
285
286
287
288
289
  	/*
  	 * Stop all Rx during the reconfig. We don't want state changes
  	 * or driver callbacks while this is in progress.
  	 */
  	local->in_reconfig = true;
  	barrier();
43d6df007   Eliad Peller   mac80211: use fre...
290
  	queue_work(system_freezable_wq, &local->restart_work);
f2753ddba   Johannes Berg   mac80211: add har...
291
292
  }
  EXPORT_SYMBOL(ieee80211_restart_hw);
26b36cfef   John W. Linville   mac80211: make AR...
293
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
294
295
296
297
298
299
300
301
302
  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...
303
  	struct in_device *idev;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
304
  	struct ieee80211_sub_if_data *sdata;
685429623   Juuso Oikarinen   mac80211: Fix cir...
305
  	struct ieee80211_bss_conf *bss_conf;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
306
  	struct ieee80211_if_managed *ifmgd;
685429623   Juuso Oikarinen   mac80211: Fix cir...
307
  	int c = 0;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
308
309
310
311
312
313
314
  
  	/* 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...
315
  	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
685429623   Juuso Oikarinen   mac80211: Fix cir...
316
  	bss_conf = &sdata->vif.bss_conf;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
317
318
319
320
  
  	/* 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...
321
  	idev = __in_dev_get_rtnl(sdata->dev);
685429623   Juuso Oikarinen   mac80211: Fix cir...
322
323
  	if (!idev)
  		return NOTIFY_DONE;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
324
  	ifmgd = &sdata->u.mgd;
8d61ffa5e   Johannes Berg   cfg80211/mac80211...
325
  	sdata_lock(sdata);
685429623   Juuso Oikarinen   mac80211: Fix cir...
326
327
328
  
  	/* Copy the addresses to the bss_conf list */
  	ifa = idev->ifa_list;
0f19b41e2   Johannes Berg   mac80211: remove ...
329
330
331
  	while (ifa) {
  		if (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN)
  			bss_conf->arp_addr_list[c] = ifa->ifa_address;
685429623   Juuso Oikarinen   mac80211: Fix cir...
332
333
334
  		ifa = ifa->ifa_next;
  		c++;
  	}
685429623   Juuso Oikarinen   mac80211: Fix cir...
335
  	bss_conf->arp_addr_cnt = c;
53d69c399   Eliad Peller   mac80211: don't c...
336
  	/* Configure driver only if associated (which also implies it is up) */
0f19b41e2   Johannes Berg   mac80211: remove ...
337
  	if (ifmgd->associated)
685429623   Juuso Oikarinen   mac80211: Fix cir...
338
339
  		ieee80211_bss_info_change_notify(sdata,
  						 BSS_CHANGED_ARP_FILTER);
685429623   Juuso Oikarinen   mac80211: Fix cir...
340

8d61ffa5e   Johannes Berg   cfg80211/mac80211...
341
  	sdata_unlock(sdata);
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
342

8bd811aa6   Zhao, Gang   mac80211: change ...
343
  	return NOTIFY_OK;
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
344
  }
26b36cfef   John W. Linville   mac80211: make AR...
345
  #endif
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
346

a65240c10   Johannes Berg   mac80211: allow d...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  #if IS_ENABLED(CONFIG_IPV6)
  static int ieee80211_ifa6_changed(struct notifier_block *nb,
  				  unsigned long data, void *arg)
  {
  	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
  	struct inet6_dev *idev = ifa->idev;
  	struct net_device *ndev = ifa->idev->dev;
  	struct ieee80211_local *local =
  		container_of(nb, struct ieee80211_local, ifa6_notifier);
  	struct wireless_dev *wdev = ndev->ieee80211_ptr;
  	struct ieee80211_sub_if_data *sdata;
  
  	/* Make sure it's our interface that got changed */
  	if (!wdev || wdev->wiphy != local->hw.wiphy)
  		return NOTIFY_DONE;
  
  	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
  
  	/*
  	 * For now only support station mode. This is mostly because
  	 * doing AP would have to handle AP_VLAN in some way ...
  	 */
  	if (sdata->vif.type != NL80211_IFTYPE_STATION)
  		return NOTIFY_DONE;
  
  	drv_ipv6_addr_change(local, sdata, idev);
8bd811aa6   Zhao, Gang   mac80211: change ...
373
  	return NOTIFY_OK;
a65240c10   Johannes Berg   mac80211: allow d...
374
375
  }
  #endif
2e161f78e   Johannes Berg   cfg80211/mac80211...
376
377
378
379
380
  /* 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,
3bfda62c5   Will Hawkins   mac80211: Allow u...
381
382
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
41e31b8b9   Antonio Quartulli   mac80211: allow u...
383
384
  			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
2e161f78e   Johannes Berg   cfg80211/mac80211...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  	},
  	[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...
410
411
412
413
414
415
416
417
418
419
420
421
  			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...
422
423
424
425
426
  			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...
427
428
  	[NL80211_IFTYPE_MESH_POINT] = {
  		.tx = 0xffff,
71839121a   Javier Cardona   mac80211: Let use...
429
430
431
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_AUTH >> 4) |
  			BIT(IEEE80211_STYPE_DEAUTH >> 4),
c7108a711   Javier Cardona   mac80211: Send me...
432
  	},
f142c6b90   Johannes Berg   mac80211: support...
433
434
435
436
437
  	[NL80211_IFTYPE_P2P_DEVICE] = {
  		.tx = 0xffff,
  		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  			BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
  	},
2e161f78e   Johannes Berg   cfg80211/mac80211...
438
  };
ef96a8420   Ben Greear   mac80211: Support...
439
440
441
442
443
444
  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 |
bc0784d95   Ben Greear   mac80211: Allow d...
445
  				IEEE80211_HT_CAP_SGI_20 |
a2e7495d6   Pawel Kulakowski   mac80211: Allow d...
446
  				IEEE80211_HT_CAP_SGI_40 |
9a07bf507   Jouni Malinen   mac80211: Allow H...
447
448
  				IEEE80211_HT_CAP_LDPC_CODING |
  				IEEE80211_HT_CAP_40MHZ_INTOLERANT),
ef96a8420   Ben Greear   mac80211: Support...
449
450
451
452
453
  	.mcs = {
  		.rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
  			     0xff, 0xff, 0xff, 0xff, 0xff, },
  	},
  };
dd5ecfeac   Johannes Berg   mac80211: support...
454
455
456
457
458
  static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = {
  	.vht_cap_info =
  		cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC |
  			    IEEE80211_VHT_CAP_SHORT_GI_80 |
  			    IEEE80211_VHT_CAP_SHORT_GI_160 |
7c209ebc7   Danek Duvall   mac80211: correct...
459
  			    IEEE80211_VHT_CAP_RXSTBC_MASK |
dd5ecfeac   Johannes Berg   mac80211: support...
460
461
462
463
464
465
466
467
468
469
470
  			    IEEE80211_VHT_CAP_TXSTBC |
  			    IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
  			    IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
  			    IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
  			    IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
  			    IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK),
  	.supp_mcs = {
  		.rx_mcs_map = cpu_to_le16(~0),
  		.tx_mcs_map = cpu_to_le16(~0),
  	},
  };
ad28757ee   Ben Greear   mac80211: allow c...
471
472
473
  struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
  					   const struct ieee80211_ops *ops,
  					   const char *requested_name)
f0706e828   Jiri Benc   [MAC80211]: Add m...
474
  {
f0706e828   Jiri Benc   [MAC80211]: Add m...
475
  	struct ieee80211_local *local;
96f5e66e8   Johannes Berg   mac80211: fix agg...
476
  	int priv_size, i;
f0706e828   Jiri Benc   [MAC80211]: Add m...
477
  	struct wiphy *wiphy;
fe57d9f5c   Johannes Berg   mac80211: track w...
478
  	bool use_chanctx;
f0706e828   Jiri Benc   [MAC80211]: Add m...
479

c0af07340   Johannes Berg   mac80211: convert...
480
481
482
483
  	if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
  		    !ops->add_interface || !ops->remove_interface ||
  		    !ops->configure_filter))
  		return NULL;
f09603a25   Johannes Berg   mac80211: add sta...
484
485
  	if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
  		return NULL;
e269d8600   Johannes Berg   mac80211: check c...
486
487
488
489
490
491
  	/* check all or no channel context operations exist */
  	i = !!ops->add_chanctx + !!ops->remove_chanctx +
  	    !!ops->change_chanctx + !!ops->assign_vif_chanctx +
  	    !!ops->unassign_vif_chanctx;
  	if (WARN_ON(i != 0 && i != 5))
  		return NULL;
fe57d9f5c   Johannes Berg   mac80211: track w...
492
  	use_chanctx = i == 5;
e269d8600   Johannes Berg   mac80211: check c...
493

f0706e828   Jiri Benc   [MAC80211]: Add m...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  	/* 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...
509
  	priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
f0706e828   Jiri Benc   [MAC80211]: Add m...
510

ad28757ee   Ben Greear   mac80211: allow c...
511
  	wiphy = wiphy_new_nm(&mac80211_config_ops, priv_size, requested_name);
f0706e828   Jiri Benc   [MAC80211]: Add m...
512
513
514
  
  	if (!wiphy)
  		return NULL;
2e161f78e   Johannes Berg   cfg80211/mac80211...
515
  	wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
207aba601   Johannes Berg   mac80211: support...
516
  	wiphy->privid = mac80211_wiphy_privid;
9bc383de3   Johannes Berg   cfg80211: introdu...
517
518
  	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
  			WIPHY_FLAG_4ADDR_AP |
ee9719245   Johannes Berg   mac80211: report ...
519
  			WIPHY_FLAG_4ADDR_STATION |
7c4ef7122   Johannes Berg   cfg80211: add fla...
520
  			WIPHY_FLAG_REPORTS_OBSS |
81ddbb5c1   Johannes Berg   mac80211: don't a...
521
522
523
524
  			WIPHY_FLAG_OFFCHAN_TX;
  
  	if (ops->remain_on_channel)
  		wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
207aba601   Johannes Berg   mac80211: support...
525

b292219fa   Johannes Berg   wireless: use OR ...
526
527
  	wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
  			   NL80211_FEATURE_SAE |
1ea6f9c0d   Johannes Berg   mac80211: handle ...
528
  			   NL80211_FEATURE_HT_IBSS |
a6dad6a26   Thomas Pedersen   mac80211: support...
529
  			   NL80211_FEATURE_VIF_TXPOWER |
b5dfae020   Ben Greear   mac80211: support...
530
  			   NL80211_FEATURE_MAC_ON_CREATE |
90f9ba9b8   Johannes Berg   Revert "mac80211:...
531
532
  			   NL80211_FEATURE_USERSPACE_MPM |
  			   NL80211_FEATURE_FULL_AP_CLIENT_STATE;
f3ca52aa5   Jouni Malinen   mac80211: Claim F...
533
  	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
a729cff8a   Johannes Berg   mac80211: impleme...
534

cd2bb512c   Sam Leffler   mac80211: add sup...
535
  	if (!ops->hw_scan)
5c95b940b   Antonio Quartulli   nl/cfg80211: forc...
536
537
  		wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
  				   NL80211_FEATURE_AP_SCAN;
cd2bb512c   Sam Leffler   mac80211: add sup...
538

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

f278ce4ff   Emmanuel Grumbach   mac80211: Set glo...
542
  	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
0c1ad2cac   Johannes Berg   mac80211: proper ...
543
  	wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
f0706e828   Jiri Benc   [MAC80211]: Add m...
544
545
  
  	local = wiphy_priv(wiphy);
de95a54b1   Johannes Berg   mac80211: pass al...
546

7bedd0cfa   Johannes Berg   mac80211: use rha...
547
548
  	if (sta_info_init(local))
  		goto err_free;
f0706e828   Jiri Benc   [MAC80211]: Add m...
549
  	local->hw.wiphy = wiphy;
1ce8e7b57   Eric Dumazet   net: ALIGN/PTR_AL...
550
  	local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
f0706e828   Jiri Benc   [MAC80211]: Add m...
551
552
  
  	local->ops = ops;
fe57d9f5c   Johannes Berg   mac80211: track w...
553
  	local->use_chanctx = use_chanctx;
f0706e828   Jiri Benc   [MAC80211]: Add m...
554

e6a9854b0   Johannes Berg   mac80211/drivers:...
555
556
557
  	/* set up some defaults */
  	local->hw.queues = 1;
  	local->hw.max_rates = 1;
78be49ec2   Helmut Schaa   mac80211: distinc...
558
  	local->hw.max_report_rates = 0;
df6ba5d80   Luciano Coelho   mac80211: add hw ...
559
  	local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
39e68712d   Helmut Schaa   mac80211: Don't u...
560
  	local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
3a25a8c8b   Johannes Berg   mac80211: add imp...
561
  	local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE;
b9a5f8cab   Jouni Malinen   nl80211: Add set/...
562
563
  	local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
  	local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
ac55d2fe0   Johannes Berg   mac80211: (select...
564
565
566
  	local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
  					 IEEE80211_RADIOTAP_MCS_HAVE_GI |
  					 IEEE80211_RADIOTAP_MCS_HAVE_BW;
516489218   Johannes Berg   mac80211: support...
567
568
  	local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
  					 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
219c38674   Alexander Bondar   mac80211: allow d...
569
570
  	local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
  	local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
1ea6f9c0d   Johannes Berg   mac80211: handle ...
571
  	local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
ef96a8420   Ben Greear   mac80211: Support...
572
  	wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
dd5ecfeac   Johannes Berg   mac80211: support...
573
  	wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
f0706e828   Jiri Benc   [MAC80211]: Add m...
574

e9a21949b   Luciano Coelho   mac80211: add ext...
575
576
577
578
579
580
  	local->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF;
  
  	wiphy->extended_capabilities = local->ext_capa;
  	wiphy->extended_capabilities_mask = local->ext_capa;
  	wiphy->extended_capabilities_len =
  		ARRAY_SIZE(local->ext_capa);
79010420c   Johannes Berg   [PATCH] mac80211:...
581
  	INIT_LIST_HEAD(&local->interfaces);
f64331d58   Johannes Berg   mac80211: keep a ...
582
  	INIT_LIST_HEAD(&local->mon_list);
2f787b0b7   YOSHIFUJI Hideaki / 吉藤英明   mac80211: Ensure ...
583
584
  
  	__hw_addr_init(&local->mc_list);
c771c9d8d   Johannes Berg   mac80211: add int...
585
  	mutex_init(&local->iflist_mtx);
a1699b75a   Johannes Berg   mac80211: unify s...
586
  	mutex_init(&local->mtx);
f0706e828   Jiri Benc   [MAC80211]: Add m...
587

ad0e2b5a0   Johannes Berg   mac80211: simplif...
588
  	mutex_init(&local->key_mtx);
3b8d81e02   Johannes Berg   mac80211: remove ...
589
  	spin_lock_init(&local->filter_lock);
f9e124fbd   Christian Lamparter   mac80211: protect...
590
  	spin_lock_init(&local->rx_path_lock);
ce7c9111a   Kalle Valo   mac80211: track m...
591
  	spin_lock_init(&local->queue_stop_reason_lock);
d01a1e658   Michal Kazior   mac80211: introdu...
592
593
  	INIT_LIST_HEAD(&local->chanctx_list);
  	mutex_init(&local->chanctx_mtx);
c2b13452b   Johannes Berg   mac80211: clean u...
594
  	INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
f0706e828   Jiri Benc   [MAC80211]: Add m...
595

f2753ddba   Johannes Berg   mac80211: add har...
596
  	INIT_WORK(&local->restart_work, ieee80211_restart_work);
164eb02d0   Simon Wunderlich   mac80211: add rad...
597
598
  	INIT_WORK(&local->radar_detected_work,
  		  ieee80211_dfs_radar_detected_work);
3ac64beec   Johannes Berg   mac80211: allow c...
599
  	INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
0f78231bf   Johannes Berg   mac80211: enable ...
600
  	local->smps_mode = IEEE80211_SMPS_OFF;
3ac64beec   Johannes Berg   mac80211: allow c...
601

520eb8207   Kalle Valo   mac80211: impleme...
602
603
604
605
606
607
  	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...
608
609
  	INIT_WORK(&local->sched_scan_stopped_work,
  		  ieee80211_sched_scan_stopped_work);
c8ff71e66   Arik Nemtsov   mac80211: TDLS: h...
610
  	INIT_WORK(&local->tdls_chsw_work, ieee80211_tdls_chsw_work);
a729cff8a   Johannes Berg   mac80211: impleme...
611
612
  	spin_lock_init(&local->ack_status_lock);
  	idr_init(&local->ack_status_frames);
a729cff8a   Johannes Berg   mac80211: impleme...
613

a6a67db2b   Johannes Berg   mac80211: refcoun...
614
  	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
2a577d987   Johannes Berg   mac80211: rework ...
615
  		skb_queue_head_init(&local->pending[i]);
a6a67db2b   Johannes Berg   mac80211: refcoun...
616
617
  		atomic_set(&local->agg_queue_stop[i], 0);
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
618
619
  	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
  		     (unsigned long)local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
620
621
622
623
  
  	tasklet_init(&local->tasklet,
  		     ieee80211_tasklet_handler,
  		     (unsigned long) local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
624
625
626
  
  	skb_queue_head_init(&local->skb_queue);
  	skb_queue_head_init(&local->skb_queue_unreliable);
c8ff71e66   Arik Nemtsov   mac80211: TDLS: h...
627
  	skb_queue_head_init(&local->skb_queue_tdls_chsw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
628

8d5c25856   Johannes Berg   mac80211: make LE...
629
  	ieee80211_alloc_led_names(local);
fe67c913f   Johannes Berg   mac80211: make LE...
630

2eb278e08   Johannes Berg   mac80211: unify S...
631
  	ieee80211_roc_setup(local);
21f835896   Johannes Berg   mac80211: impleme...
632

99ee7cae3   Johannes Berg   mac80211: add sup...
633
634
  	local->hw.radiotap_timestamp.units_pos = -1;
  	local->hw.radiotap_timestamp.accuracy = -1;
005e472b4   Johannes Berg   mac80211: remove ...
635
  	return &local->hw;
7bedd0cfa   Johannes Berg   mac80211: use rha...
636
637
638
   err_free:
  	wiphy_free(wiphy);
  	return NULL;
f0706e828   Jiri Benc   [MAC80211]: Add m...
639
  }
ad28757ee   Ben Greear   mac80211: allow c...
640
  EXPORT_SYMBOL(ieee80211_alloc_hw_nm);
f0706e828   Jiri Benc   [MAC80211]: Add m...
641

2475b1cc0   Max Stepanov   mac80211: add gen...
642
  static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
f0706e828   Jiri Benc   [MAC80211]: Add m...
643
  {
2475b1cc0   Max Stepanov   mac80211: add gen...
644
645
  	bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
  			  IS_ERR(local->wep_rx_tfm));
30686bf7f   Johannes Berg   mac80211: convert...
646
  	bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE);
2475b1cc0   Max Stepanov   mac80211: add gen...
647
648
  	int n_suites = 0, r = 0, w = 0;
  	u32 *suites;
25e47c18a   Johannes Berg   cfg80211: add cip...
649
  	static const u32 cipher_suites[] = {
5daa8a8e6   Johannes Berg   mac80211: dont ad...
650
  		/* keep WEP first, it may be removed below */
25e47c18a   Johannes Berg   cfg80211: add cip...
651
652
653
654
  		WLAN_CIPHER_SUITE_WEP40,
  		WLAN_CIPHER_SUITE_WEP104,
  		WLAN_CIPHER_SUITE_TKIP,
  		WLAN_CIPHER_SUITE_CCMP,
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
655
  		WLAN_CIPHER_SUITE_CCMP_256,
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
656
657
  		WLAN_CIPHER_SUITE_GCMP,
  		WLAN_CIPHER_SUITE_GCMP_256,
25e47c18a   Johannes Berg   cfg80211: add cip...
658
659
  
  		/* keep last -- depends on hw flags! */
56c52da2d   Jouni Malinen   mac80111: Add BIP...
660
661
  		WLAN_CIPHER_SUITE_AES_CMAC,
  		WLAN_CIPHER_SUITE_BIP_CMAC_256,
8ade538bf   Jouni Malinen   mac80111: Add BIP...
662
663
  		WLAN_CIPHER_SUITE_BIP_GMAC_128,
  		WLAN_CIPHER_SUITE_BIP_GMAC_256,
25e47c18a   Johannes Berg   cfg80211: add cip...
664
  	};
8318d78a4   Johannes Berg   cfg80211 API for ...
665

30686bf7f   Johannes Berg   mac80211: convert...
666
  	if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) ||
fa7e1fbcb   Johannes Berg   mac80211: allow d...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
  	    local->hw.wiphy->cipher_suites) {
  		/* If the driver advertises, or doesn't support SW crypto,
  		 * we only need to remove WEP if necessary.
  		 */
  		if (have_wep)
  			return 0;
  
  		/* well if it has _no_ ciphers ... fine */
  		if (!local->hw.wiphy->n_cipher_suites)
  			return 0;
  
  		/* Driver provides cipher suites, but we need to exclude WEP */
  		suites = kmemdup(local->hw.wiphy->cipher_suites,
  				 sizeof(u32) * local->hw.wiphy->n_cipher_suites,
  				 GFP_KERNEL);
  		if (!suites)
  			return -ENOMEM;
2475b1cc0   Max Stepanov   mac80211: add gen...
684

fa7e1fbcb   Johannes Berg   mac80211: allow d...
685
686
687
688
689
690
691
692
693
694
695
696
697
  		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;
  		}
  	} else if (!local->hw.cipher_schemes) {
  		/* If the driver doesn't have cipher schemes, there's nothing
  		 * else to do other than assign the (software supported and
  		 * perhaps offloaded) cipher suites.
  		 */
2475b1cc0   Max Stepanov   mac80211: add gen...
698
699
700
701
  		local->hw.wiphy->cipher_suites = cipher_suites;
  		local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
  
  		if (!have_mfp)
8ade538bf   Jouni Malinen   mac80111: Add BIP...
702
  			local->hw.wiphy->n_cipher_suites -= 4;
2475b1cc0   Max Stepanov   mac80211: add gen...
703
704
705
706
707
  
  		if (!have_wep) {
  			local->hw.wiphy->cipher_suites += 2;
  			local->hw.wiphy->n_cipher_suites -= 2;
  		}
fa7e1fbcb   Johannes Berg   mac80211: allow d...
708
  		/* not dynamically allocated, so just return */
2475b1cc0   Max Stepanov   mac80211: add gen...
709
  		return 0;
fa7e1fbcb   Johannes Berg   mac80211: allow d...
710
711
  	} else {
  		const struct ieee80211_cipher_scheme *cs;
2475b1cc0   Max Stepanov   mac80211: add gen...
712

fa7e1fbcb   Johannes Berg   mac80211: allow d...
713
714
715
716
717
  		cs = local->hw.cipher_schemes;
  
  		/* Driver specifies cipher schemes only (but not cipher suites
  		 * including the schemes)
  		 *
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
718
  		 * We start counting ciphers defined by schemes, TKIP, CCMP,
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
719
  		 * CCMP-256, GCMP, and GCMP-256
2475b1cc0   Max Stepanov   mac80211: add gen...
720
  		 */
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
721
  		n_suites = local->hw.n_cipher_schemes + 5;
2475b1cc0   Max Stepanov   mac80211: add gen...
722
723
724
725
  
  		/* check if we have WEP40 and WEP104 */
  		if (have_wep)
  			n_suites += 2;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
726
727
728
  		/* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128,
  		 * BIP-GMAC-256
  		 */
2475b1cc0   Max Stepanov   mac80211: add gen...
729
  		if (have_mfp)
8ade538bf   Jouni Malinen   mac80111: Add BIP...
730
  			n_suites += 4;
2475b1cc0   Max Stepanov   mac80211: add gen...
731
732
733
734
735
736
  
  		suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
  		if (!suites)
  			return -ENOMEM;
  
  		suites[w++] = WLAN_CIPHER_SUITE_CCMP;
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
737
  		suites[w++] = WLAN_CIPHER_SUITE_CCMP_256;
2475b1cc0   Max Stepanov   mac80211: add gen...
738
  		suites[w++] = WLAN_CIPHER_SUITE_TKIP;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
739
740
  		suites[w++] = WLAN_CIPHER_SUITE_GCMP;
  		suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
2475b1cc0   Max Stepanov   mac80211: add gen...
741
742
743
744
745
  
  		if (have_wep) {
  			suites[w++] = WLAN_CIPHER_SUITE_WEP40;
  			suites[w++] = WLAN_CIPHER_SUITE_WEP104;
  		}
56c52da2d   Jouni Malinen   mac80111: Add BIP...
746
  		if (have_mfp) {
2475b1cc0   Max Stepanov   mac80211: add gen...
747
  			suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
56c52da2d   Jouni Malinen   mac80111: Add BIP...
748
  			suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
749
750
  			suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128;
  			suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256;
56c52da2d   Jouni Malinen   mac80111: Add BIP...
751
  		}
2475b1cc0   Max Stepanov   mac80211: add gen...
752

e3a55b539   Johannes Berg   mac80211: validat...
753
  		for (r = 0; r < local->hw.n_cipher_schemes; r++) {
2475b1cc0   Max Stepanov   mac80211: add gen...
754
  			suites[w++] = cs[r].cipher;
94c78cb45   Johannes Berg   mac80211: fix mem...
755
756
  			if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) {
  				kfree(suites);
e3a55b539   Johannes Berg   mac80211: validat...
757
  				return -EINVAL;
94c78cb45   Johannes Berg   mac80211: fix mem...
758
  			}
e3a55b539   Johannes Berg   mac80211: validat...
759
  		}
2475b1cc0   Max Stepanov   mac80211: add gen...
760
761
762
763
764
765
766
767
768
769
770
771
772
  	}
  
  	local->hw.wiphy->cipher_suites = suites;
  	local->hw.wiphy->n_cipher_suites = w;
  	local->wiphy_ciphers_allocated = true;
  
  	return 0;
  }
  
  int ieee80211_register_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
  	int result, i;
57fbcce37   Johannes Berg   cfg80211: remove ...
773
  	enum nl80211_band band;
2475b1cc0   Max Stepanov   mac80211: add gen...
774
775
776
777
  	int channels, max_bitrates;
  	bool supp_ht, supp_vht;
  	netdev_features_t feature_whitelist;
  	struct cfg80211_chan_def dflt_chandef = {};
30686bf7f   Johannes Berg   mac80211: convert...
778
  	if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
3a25a8c8b   Johannes Berg   mac80211: add imp...
779
780
781
  	    (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
  	     local->hw.offchannel_tx_hw_queue >= local->hw.queues))
  		return -EINVAL;
a7a6bdd06   Arik Nemtsov   mac80211: introdu...
782
783
  	if ((hw->wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
  	    (!local->ops->tdls_channel_switch ||
8a4d32f30   Arik Nemtsov   mac80211: add TDL...
784
785
  	     !local->ops->tdls_cancel_channel_switch ||
  	     !local->ops->tdls_recv_channel_switch))
a7a6bdd06   Arik Nemtsov   mac80211: introdu...
786
  		return -EOPNOTSUPP;
f3fe4e93d   Sara Sharon   mac80211: add a H...
787
788
789
  	if (WARN_ON(ieee80211_hw_check(hw, SUPPORTS_TX_FRAG) &&
  		    !local->ops->set_frag_threshold))
  		return -EINVAL;
708d50edb   Ayala Beker   mac80211: add boi...
790
791
792
793
  	if (WARN_ON(local->hw.wiphy->interface_modes &
  			BIT(NL80211_IFTYPE_NAN) &&
  		    (!local->ops->start_nan || !local->ops->stop_nan)))
  		return -EINVAL;
38bb3e9da   Larry Finger   mac80211: Fix bui...
794
  #ifdef CONFIG_PM
964dc9e2c   Johannes Berg   cfg80211: take Wo...
795
  	if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
eecc48000   Johannes Berg   mac80211: add bas...
796
  		return -EINVAL;
dfb89c56a   Johannes Berg   cfg80211: don't a...
797
  #endif
eecc48000   Johannes Berg   mac80211: add bas...
798

fe57d9f5c   Johannes Berg   mac80211: track w...
799
800
801
802
803
804
805
806
807
  	if (!local->use_chanctx) {
  		for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
  			const struct ieee80211_iface_combination *comb;
  
  			comb = &local->hw.wiphy->iface_combinations[i];
  
  			if (comb->num_different_channels > 1)
  				return -EINVAL;
  		}
746a33658   Johannes Berg   mac80211: fix WDS...
808
  	} else {
fe57d9f5c   Johannes Berg   mac80211: track w...
809
810
811
812
813
814
815
  		/*
  		 * WDS is currently prohibited when channel contexts are used
  		 * because there's no clear definition of which channel WDS
  		 * type interfaces use
  		 */
  		if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
  			return -EINVAL;
164eb02d0   Simon Wunderlich   mac80211: add rad...
816

486cf4c08   Michal Kazior   mac80211: enable ...
817
  		/* DFS is not supported with multi-channel combinations yet */
164eb02d0   Simon Wunderlich   mac80211: add rad...
818
819
820
821
  		for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
  			const struct ieee80211_iface_combination *comb;
  
  			comb = &local->hw.wiphy->iface_combinations[i];
486cf4c08   Michal Kazior   mac80211: enable ...
822
823
  			if (comb->radar_detect_widths &&
  			    comb->num_different_channels > 1)
164eb02d0   Simon Wunderlich   mac80211: add rad...
824
825
  				return -EINVAL;
  		}
fe57d9f5c   Johannes Berg   mac80211: track w...
826
  	}
72d787285   Arik Nemtsov   mac80211: allow l...
827
828
  	/* Only HW csum features are currently compatible with mac80211 */
  	feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
80616c0db   Johannes Berg   mac80211: allow s...
829
  			    NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA |
e03521232   Sara Sharon   mac80211: add NET...
830
  			    NETIF_F_GSO_SOFTWARE | NETIF_F_RXCSUM;
72d787285   Arik Nemtsov   mac80211: allow l...
831
832
  	if (WARN_ON(hw->netdev_features & ~feature_whitelist))
  		return -EINVAL;
78be49ec2   Helmut Schaa   mac80211: distinc...
833
834
  	if (hw->max_report_rates == 0)
  		hw->max_report_rates = hw->max_rates;
04ecd2578   Johannes Berg   mac80211: track n...
835
  	local->rx_chains = 1;
8318d78a4   Johannes Berg   cfg80211 API for ...
836
837
838
839
840
  	/*
  	 * 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:...
841
  	channels = 0;
de95a54b1   Johannes Berg   mac80211: pass al...
842
  	max_bitrates = 0;
5ef2d41af   Johannes Berg   mac80211: include...
843
  	supp_ht = false;
ba0afa2f2   Mahesh Palivela   mac80211: include...
844
  	supp_vht = false;
57fbcce37   Johannes Berg   cfg80211: remove ...
845
  	for (band = 0; band < NUM_NL80211_BANDS; band++) {
8318d78a4   Johannes Berg   cfg80211 API for ...
846
847
848
  		struct ieee80211_supported_band *sband;
  
  		sband = local->hw.wiphy->bands[band];
de95a54b1   Johannes Berg   mac80211: pass al...
849
850
  		if (!sband)
  			continue;
fffa4b1c1   Karl Beldan   mac80211: adjust ...
851
852
853
854
855
  
  		if (!dflt_chandef.chan) {
  			cfg80211_chandef_create(&dflt_chandef,
  						&sband->channels[0],
  						NL80211_CHAN_NO_HT);
8318d78a4   Johannes Berg   cfg80211 API for ...
856
  			/* init channel we're on */
fffa4b1c1   Karl Beldan   mac80211: adjust ...
857
858
859
860
861
  			if (!local->use_chanctx && !local->_oper_chandef.chan) {
  				local->hw.conf.chandef = dflt_chandef;
  				local->_oper_chandef = dflt_chandef;
  			}
  			local->monitor_chandef = dflt_chandef;
8318d78a4   Johannes Berg   cfg80211 API for ...
862
  		}
fffa4b1c1   Karl Beldan   mac80211: adjust ...
863

de95a54b1   Johannes Berg   mac80211: pass al...
864
865
866
867
  		channels += sband->n_channels;
  
  		if (max_bitrates < sband->n_bitrates)
  			max_bitrates = sband->n_bitrates;
5ef2d41af   Johannes Berg   mac80211: include...
868
  		supp_ht = supp_ht || sband->ht_cap.ht_supported;
ba0afa2f2   Mahesh Palivela   mac80211: include...
869
  		supp_vht = supp_vht || sband->vht_cap.vht_supported;
04ecd2578   Johannes Berg   mac80211: track n...
870

43071d8fb   Felix Fietkau   mac80211: initial...
871
872
  		if (!sband->ht_cap.ht_supported)
  			continue;
04ecd2578   Johannes Berg   mac80211: track n...
873
874
  
  		/* TODO: consider VHT for RX chains, hopefully it's the same */
43071d8fb   Felix Fietkau   mac80211: initial...
875
876
877
878
879
880
881
  		local->rx_chains =
  			max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
  			    local->rx_chains);
  
  		/* no need to mask, SM_PS_DISABLED has all bits set */
  		sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
  			             IEEE80211_HT_CAP_SM_PS_SHIFT;
8318d78a4   Johannes Berg   cfg80211 API for ...
882
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
883

f59ac0481   Luis R. Rodriguez   cfg80211: keep tr...
884
  	/* if low-level driver supports AP, we also support VLAN */
7527a782e   Johannes Berg   cfg80211: adverti...
885
886
887
888
  	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...
889
890
  
  	/* mac80211 always supports monitor */
7527a782e   Johannes Berg   cfg80211: adverti...
891
892
  	hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
  	hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
55de908ab   Johannes Berg   mac80211: use cha...
893
  	/* mac80211 doesn't support more than one IBSS interface right now */
8e621fc90   Johannes Berg   mac80211: verify ...
894
895
896
897
898
  	for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
  		const struct ieee80211_iface_combination *c;
  		int j;
  
  		c = &hw->wiphy->iface_combinations[i];
8e621fc90   Johannes Berg   mac80211: verify ...
899
900
901
902
903
  		for (j = 0; j < c->n_limits; j++)
  			if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
  			    c->limits[j].max > 1)
  				return -EINVAL;
  	}
5b0ec94f9   Johannes Berg   mac80211: fix mem...
904
905
906
907
  	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
  				      sizeof(void *) * channels, GFP_KERNEL);
  	if (!local->int_scan_req)
  		return -ENOMEM;
57fbcce37   Johannes Berg   cfg80211: remove ...
908
  	for (band = 0; band < NUM_NL80211_BANDS; band++) {
5b0ec94f9   Johannes Berg   mac80211: fix mem...
909
910
911
912
  		if (!local->hw.wiphy->bands[band])
  			continue;
  		local->int_scan_req->rates[band] = (u32) -1;
  	}
5eb5a52da   Johannes Berg   mac80211: fix mes...
913
914
915
916
  #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...
917
918
919
920
  	/* 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...
921
922
  	/* mac80211 supports control port protocol changing */
  	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
30686bf7f   Johannes Berg   mac80211: convert...
923
  	if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) {
77965c970   Johannes Berg   cfg80211: clean u...
924
  		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
30686bf7f   Johannes Berg   mac80211: convert...
925
  	} else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) {
77965c970   Johannes Berg   cfg80211: clean u...
926
  		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
525120727   andrea merello   mac80211: add che...
927
928
929
930
931
  		if (hw->max_signal <= 0) {
  			result = -EINVAL;
  			goto fail_wiphy_register;
  		}
  	}
77965c970   Johannes Berg   cfg80211: clean u...
932

de95a54b1   Johannes Berg   mac80211: pass al...
933
934
935
  	/*
  	 * Calculate scan IE length -- we need this to alloc
  	 * memory and to subtract from the driver limit. It
dc9f48ce7   Jouni Malinen   mac80211: Fix sca...
936
  	 * includes the DS Params, (extended) supported rates, and HT
de95a54b1   Johannes Berg   mac80211: pass al...
937
938
  	 * information -- SSID is the driver's responsibility.
  	 */
dc9f48ce7   Jouni Malinen   mac80211: Fix sca...
939
940
  	local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
  		3 /* DS Params */;
5ef2d41af   Johannes Berg   mac80211: include...
941
942
  	if (supp_ht)
  		local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
de95a54b1   Johannes Berg   mac80211: pass al...
943

d0e6c21ac   Karl Beldan   mac80211: let dri...
944
  	if (supp_vht)
ba0afa2f2   Mahesh Palivela   mac80211: include...
945
  		local->scan_ies_len +=
d4950281d   Mahesh Palivela   ieee80211: Rename...
946
  			2 + sizeof(struct ieee80211_vht_cap);
ba0afa2f2   Mahesh Palivela   mac80211: include...
947

de95a54b1   Johannes Berg   mac80211: pass al...
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
  	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;
2475b1cc0   Max Stepanov   mac80211: add gen...
963
964
965
966
967
968
  	WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes,
  					 local->hw.n_cipher_schemes));
  
  	result = ieee80211_init_cipher_suites(local);
  	if (result < 0)
  		goto fail_wiphy_register;
25e47c18a   Johannes Berg   cfg80211: add cip...
969

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

dfe018bf9   Arik Nemtsov   mac80211: handle ...
973
974
975
  	/* 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;
e9a21949b   Luciano Coelho   mac80211: add ext...
976
  	/* mac80211 supports eCSA, if the driver supports STA CSA at all */
30686bf7f   Johannes Berg   mac80211: convert...
977
  	if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA))
e9a21949b   Luciano Coelho   mac80211: add ext...
978
  		local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
0d06d9ba9   Andrei Otcheretianski   mac80211: Support...
979
  	local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
f0706e828   Jiri Benc   [MAC80211]: Add m...
980
981
  	result = wiphy_register(local->hw.wiphy);
  	if (result < 0)
2a5193119   Johannes Berg   cfg80211/nl80211:...
982
  		goto fail_wiphy_register;
f0706e828   Jiri Benc   [MAC80211]: Add m...
983

e25300836   Johannes Berg   mac80211: use mul...
984
985
986
987
  	/*
  	 * We use the number of queues for feature tests (QoS, HT) internally
  	 * so restrict them appropriately.
  	 */
e25300836   Johannes Berg   mac80211: use mul...
988
989
  	if (hw->queues > IEEE80211_MAX_QUEUES)
  		hw->queues = IEEE80211_MAX_QUEUES;
e25300836   Johannes Berg   mac80211: use mul...
990

42935ecaf   Luis R. Rodriguez   mac80211: redefin...
991
  	local->workqueue =
d8537548c   Kees Cook   drivers: avoid fo...
992
  		alloc_ordered_workqueue("%s", 0, wiphy_name(local->hw.wiphy));
42935ecaf   Luis R. Rodriguez   mac80211: redefin...
993
  	if (!local->workqueue) {
f0706e828   Jiri Benc   [MAC80211]: Add m...
994
995
996
  		result = -ENOMEM;
  		goto fail_workqueue;
  	}
b306f4530   Johannes Berg   [PATCH] mac80211:...
997
998
999
1000
1001
  	/*
  	 * 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:...
1002
  	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
a2fe81667   Helmut Schaa   mac80211: Build T...
1003
  				   IEEE80211_TX_STATUS_HEADROOM);
b306f4530   Johannes Berg   [PATCH] mac80211:...
1004

e9f207f0f   Jiri Benc   [MAC80211]: Add d...
1005
  	debugfs_hw_add(local);
b446918b7   Helmut Schaa   mac80211: use lis...
1006
1007
1008
1009
  	/*
  	 * 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...
1010
  	if (local->hw.max_listen_interval == 0)
b446918b7   Helmut Schaa   mac80211: use lis...
1011
  		local->hw.max_listen_interval = 5;
ea95bba41   Tomas Winkler   mac80211: make li...
1012
1013
  
  	local->hw.conf.listen_interval = local->hw.max_listen_interval;
ff6163810   Juuso Oikarinen   mac80211: Fix ps-...
1014
  	local->dynamic_ps_forced_timeout = -1;
195e294d2   Juuso Oikarinen   mac80211: Determi...
1015

167e33f4f   Ayala Beker   mac80211: Impleme...
1016
1017
  	if (!local->hw.max_nan_de_entries)
  		local->hw.max_nan_de_entries = IEEE80211_MAX_NAN_INSTANCE_ID;
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
1018
  	result = ieee80211_wep_init(local);
3473187d2   John W. Linville   mac80211: remove ...
1019
  	if (result < 0)
0fb9a9ec2   Joe Perches   net/mac80211: Use...
1020
1021
1022
  		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d
  ",
  			    result);
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
1023

24d47300d   Karl Beldan   mac80211: set hw ...
1024
  	local->hw.conf.flags = IEEE80211_CONF_IDLE;
b57e6b560   Mohammed Shafi Shajakhan   mac80211: Fix a r...
1025
  	ieee80211_led_init(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1026
  	rtnl_lock();
f0706e828   Jiri Benc   [MAC80211]: Add m...
1027

830f90386   Johannes Berg   mac80211: allow d...
1028
1029
  	result = ieee80211_init_rate_ctrl_alg(local,
  					      hw->rate_control_algorithm);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1030
  	if (result < 0) {
0fb9a9ec2   Joe Perches   net/mac80211: Use...
1031
1032
1033
  		wiphy_debug(local->hw.wiphy,
  			    "Failed to initialize rate control algorithm
  ");
f0706e828   Jiri Benc   [MAC80211]: Add m...
1034
1035
  		goto fail_rate;
  	}
8dffff216   Johannes Berg   mac80211: only cr...
1036
  	/* add one default STA interface if supported */
e27513fbd   Ben Greear   mac80211: support...
1037
  	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
30686bf7f   Johannes Berg   mac80211: convert...
1038
  	    !ieee80211_hw_check(hw, NO_AUTO_VIF)) {
6bab2e19c   Tom Gundersen   cfg80211: pass na...
1039
  		result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL,
8dffff216   Johannes Berg   mac80211: only cr...
1040
1041
  					  NL80211_IFTYPE_STATION, NULL);
  		if (result)
0fb9a9ec2   Joe Perches   net/mac80211: Use...
1042
1043
1044
  			wiphy_warn(local->hw.wiphy,
  				   "Failed to add default virtual iface
  ");
8dffff216   Johannes Berg   mac80211: only cr...
1045
  	}
f0706e828   Jiri Benc   [MAC80211]: Add m...
1046

f0706e828   Jiri Benc   [MAC80211]: Add m...
1047
  	rtnl_unlock();
fa962b921   Michal Kazior   mac80211: impleme...
1048
1049
1050
  	result = ieee80211_txq_setup_flows(local);
  	if (result)
  		goto fail_flows;
26b36cfef   John W. Linville   mac80211: make AR...
1051
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
1052
1053
1054
1055
  	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...
1056
  #endif
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
1057

a65240c10   Johannes Berg   mac80211: allow d...
1058
1059
1060
1061
1062
1063
  #if IS_ENABLED(CONFIG_IPV6)
  	local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
  	result = register_inet6addr_notifier(&local->ifa6_notifier);
  	if (result)
  		goto fail_ifa6;
  #endif
f0706e828   Jiri Benc   [MAC80211]: Add m...
1064
  	return 0;
a65240c10   Johannes Berg   mac80211: allow d...
1065
1066
  #if IS_ENABLED(CONFIG_IPV6)
   fail_ifa6:
93c08c329   Juuso Oikarinen   mac80211: Fix com...
1067
  #ifdef CONFIG_INET
a65240c10   Johannes Berg   mac80211: allow d...
1068
1069
1070
1071
  	unregister_inetaddr_notifier(&local->ifa_notifier);
  #endif
  #endif
  #if defined(CONFIG_INET) || defined(CONFIG_IPV6)
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
1072
   fail_ifa:
93c08c329   Juuso Oikarinen   mac80211: Fix com...
1073
  #endif
fa962b921   Michal Kazior   mac80211: impleme...
1074
1075
  	ieee80211_txq_teardown_flows(local);
   fail_flows:
54330bf63   Johannes Berg   mac80211: fix HW ...
1076
1077
  	rtnl_lock();
  	rate_control_deinitialize(local);
10f644a47   Johannes Berg   mac80211: disable...
1078
  	ieee80211_remove_interfaces(local);
10f644a47   Johannes Berg   mac80211: disable...
1079
   fail_rate:
f0706e828   Jiri Benc   [MAC80211]: Add m...
1080
  	rtnl_unlock();
54330bf63   Johannes Berg   mac80211: fix HW ...
1081
  	ieee80211_led_exit(local);
d4c4a9a1b   Alan Jenkins   mac80211: fix mod...
1082
  	ieee80211_wep_free(local);
42935ecaf   Luis R. Rodriguez   mac80211: redefin...
1083
  	destroy_workqueue(local->workqueue);
10f644a47   Johannes Berg   mac80211: disable...
1084
   fail_workqueue:
f0706e828   Jiri Benc   [MAC80211]: Add m...
1085
  	wiphy_unregister(local->hw.wiphy);
10f644a47   Johannes Berg   mac80211: disable...
1086
   fail_wiphy_register:
3ffc2a905   Johannes Berg   mac80211: allow v...
1087
1088
  	if (local->wiphy_ciphers_allocated)
  		kfree(local->hw.wiphy->cipher_suites);
11ba964d4   Johannes Berg   mac80211: fix reg...
1089
  	kfree(local->int_scan_req);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1090
1091
1092
  	return result;
  }
  EXPORT_SYMBOL(ieee80211_register_hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1093
1094
1095
  void ieee80211_unregister_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1096
1097
1098
  
  	tasklet_kill(&local->tx_pending_tasklet);
  	tasklet_kill(&local->tasklet);
26b36cfef   John W. Linville   mac80211: make AR...
1099
  #ifdef CONFIG_INET
2b2c009ec   Juuso Oikarinen   mac80211: Add sup...
1100
  	unregister_inetaddr_notifier(&local->ifa_notifier);
26b36cfef   John W. Linville   mac80211: make AR...
1101
  #endif
a65240c10   Johannes Berg   mac80211: allow d...
1102
1103
1104
  #if IS_ENABLED(CONFIG_IPV6)
  	unregister_inet6addr_notifier(&local->ifa6_notifier);
  #endif
4ae9a73be   Toke Høiland-Jørgensen   mac80211: Run TXQ...
1105
  	ieee80211_txq_teardown_flows(local);
10f644a47   Johannes Berg   mac80211: disable...
1106

f0706e828   Jiri Benc   [MAC80211]: Add m...
1107
  	rtnl_lock();
79010420c   Johannes Berg   [PATCH] mac80211:...
1108
1109
1110
1111
1112
  	/*
  	 * 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 ...
1113
  	ieee80211_remove_interfaces(local);
5b2812e92   Johannes Berg   [PATCH] mac80211:...
1114

f0706e828   Jiri Benc   [MAC80211]: Add m...
1115
  	rtnl_unlock();
aaa016ccd   Johannes Berg   mac80211: rewrite...
1116
  	cancel_delayed_work_sync(&local->roc_work);
258086a48   Christian Lamparter   mac80211: cancel ...
1117
  	cancel_work_sync(&local->restart_work);
3ac64beec   Johannes Berg   mac80211: allow c...
1118
  	cancel_work_sync(&local->reconfig_filter);
c8ff71e66   Arik Nemtsov   mac80211: TDLS: h...
1119
  	cancel_work_sync(&local->tdls_chsw_work);
18db594a1   Johannes Berg   mac80211: fix sch...
1120
  	flush_work(&local->sched_scan_stopped_work);
4a1990682   Johannes Berg   mac80211: disenta...
1121
  	flush_work(&local->radar_detected_work);
3ac64beec   Johannes Berg   mac80211: allow c...
1122

f0706e828   Jiri Benc   [MAC80211]: Add m...
1123
  	ieee80211_clear_tx_pending(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1124
  	rate_control_deinitialize(local);
f64f9e719   Joe Perches   net: Move && and ...
1125
1126
  	if (skb_queue_len(&local->skb_queue) ||
  	    skb_queue_len(&local->skb_queue_unreliable))
0fb9a9ec2   Joe Perches   net/mac80211: Use...
1127
1128
  		wiphy_warn(local->hw.wiphy, "skb_queue not empty
  ");
f0706e828   Jiri Benc   [MAC80211]: Add m...
1129
1130
  	skb_queue_purge(&local->skb_queue);
  	skb_queue_purge(&local->skb_queue_unreliable);
c8ff71e66   Arik Nemtsov   mac80211: TDLS: h...
1131
  	skb_queue_purge(&local->skb_queue_tdls_chsw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1132

42935ecaf   Luis R. Rodriguez   mac80211: redefin...
1133
  	destroy_workqueue(local->workqueue);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1134
1135
1136
  	wiphy_unregister(local->hw.wiphy);
  	ieee80211_wep_free(local);
  	ieee80211_led_exit(local);
5ba63533b   Johannes Berg   cfg80211: fix ali...
1137
  	kfree(local->int_scan_req);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1138
1139
  }
  EXPORT_SYMBOL(ieee80211_unregister_hw);
a729cff8a   Johannes Berg   mac80211: impleme...
1140
1141
1142
1143
1144
1145
1146
  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...
1147
1148
1149
  void ieee80211_free_hw(struct ieee80211_hw *hw)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
c771c9d8d   Johannes Berg   mac80211: add int...
1150
  	mutex_destroy(&local->iflist_mtx);
a1699b75a   Johannes Berg   mac80211: unify s...
1151
  	mutex_destroy(&local->mtx);
c771c9d8d   Johannes Berg   mac80211: add int...
1152

3ffc2a905   Johannes Berg   mac80211: allow v...
1153
1154
  	if (local->wiphy_ciphers_allocated)
  		kfree(local->hw.wiphy->cipher_suites);
a729cff8a   Johannes Berg   mac80211: impleme...
1155
1156
1157
  	idr_for_each(&local->ack_status_frames,
  		     ieee80211_free_ack_frame, NULL);
  	idr_destroy(&local->ack_status_frames);
54330bf63   Johannes Berg   mac80211: fix HW ...
1158
  	sta_info_stop(local);
8d5c25856   Johannes Berg   mac80211: make LE...
1159
  	ieee80211_free_led_names(local);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1160
1161
1162
  	wiphy_free(local->hw.wiphy);
  }
  EXPORT_SYMBOL(ieee80211_free_hw);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1163
1164
1165
1166
  static int __init ieee80211_init(void)
  {
  	struct sk_buff *skb;
  	int ret;
e039fa4a4   Johannes Berg   mac80211: move TX...
1167
1168
  	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...
1169
  		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
f0706e828   Jiri Benc   [MAC80211]: Add m...
1170

cccf129f8   Felix Fietkau   mac80211: add the...
1171
1172
1173
  	ret = rc80211_minstrel_init();
  	if (ret)
  		return ret;
ec8aa669b   Felix Fietkau   mac80211: add the...
1174
1175
1176
  	ret = rc80211_minstrel_ht_init();
  	if (ret)
  		goto err_minstrel;
47846c9b0   Johannes Berg   mac80211: reduce ...
1177
1178
1179
  	ret = ieee80211_iface_init();
  	if (ret)
  		goto err_netdev;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
1180

f0706e828   Jiri Benc   [MAC80211]: Add m...
1181
  	return 0;
47846c9b0   Johannes Berg   mac80211: reduce ...
1182
   err_netdev:
ec8aa669b   Felix Fietkau   mac80211: add the...
1183
1184
  	rc80211_minstrel_ht_exit();
   err_minstrel:
47846c9b0   Johannes Berg   mac80211: reduce ...
1185
1186
1187
  	rc80211_minstrel_exit();
  
  	return ret;
f0706e828   Jiri Benc   [MAC80211]: Add m...
1188
  }
f0706e828   Jiri Benc   [MAC80211]: Add m...
1189
1190
  static void __exit ieee80211_exit(void)
  {
ec8aa669b   Felix Fietkau   mac80211: add the...
1191
  	rc80211_minstrel_ht_exit();
cccf129f8   Felix Fietkau   mac80211: add the...
1192
  	rc80211_minstrel_exit();
ac71c691e   Johannes Berg   mac80211: make si...
1193

bf7cd94dc   Johannes Berg   mac80211: clean u...
1194
  	ieee80211s_stop();
902acc789   Johannes Berg   mac80211: clean u...
1195

47846c9b0   Johannes Berg   mac80211: reduce ...
1196
  	ieee80211_iface_exit();
d07c7cf49   Johannes Berg   mac80211: add mis...
1197
1198
  
  	rcu_barrier();
f0706e828   Jiri Benc   [MAC80211]: Add m...
1199
  }
ca9938fea   Johannes Berg   [PATCH] mac80211:...
1200
  subsys_initcall(ieee80211_init);
f0706e828   Jiri Benc   [MAC80211]: Add m...
1201
1202
1203
1204
  module_exit(ieee80211_exit);
  
  MODULE_DESCRIPTION("IEEE 802.11 subsystem");
  MODULE_LICENSE("GPL");