Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Copyright 2002-2005, Instant802 Networks, Inc.
4 : : * Copyright 2005-2006, Devicescape Software, Inc.
5 : : * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
6 : : * Copyright 2013-2014 Intel Mobile Communications GmbH
7 : : * Copyright (C) 2017 Intel Deutschland GmbH
8 : : * Copyright (C) 2018 - 2019 Intel Corporation
9 : : */
10 : :
11 : : #include <net/mac80211.h>
12 : : #include <linux/module.h>
13 : : #include <linux/fips.h>
14 : : #include <linux/init.h>
15 : : #include <linux/netdevice.h>
16 : : #include <linux/types.h>
17 : : #include <linux/slab.h>
18 : : #include <linux/skbuff.h>
19 : : #include <linux/etherdevice.h>
20 : : #include <linux/if_arp.h>
21 : : #include <linux/rtnetlink.h>
22 : : #include <linux/bitmap.h>
23 : : #include <linux/inetdevice.h>
24 : : #include <net/net_namespace.h>
25 : : #include <net/cfg80211.h>
26 : : #include <net/addrconf.h>
27 : :
28 : : #include "ieee80211_i.h"
29 : : #include "driver-ops.h"
30 : : #include "rate.h"
31 : : #include "mesh.h"
32 : : #include "wep.h"
33 : : #include "led.h"
34 : : #include "debugfs.h"
35 : :
36 : 0 : void ieee80211_configure_filter(struct ieee80211_local *local)
37 : : {
38 : 0 : u64 mc;
39 : 0 : unsigned int changed_flags;
40 : 0 : unsigned int new_flags = 0;
41 : :
42 [ # # ]: 0 : if (atomic_read(&local->iff_allmultis))
43 : 0 : new_flags |= FIF_ALLMULTI;
44 : :
45 [ # # # # : 0 : if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning) ||
# # ]
46 : : test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning))
47 : 0 : new_flags |= FIF_BCN_PRBRESP_PROMISC;
48 : :
49 [ # # # # ]: 0 : if (local->fif_probe_req || local->probe_req_reg)
50 : 0 : new_flags |= FIF_PROBE_REQ;
51 : :
52 [ # # ]: 0 : if (local->fif_fcsfail)
53 : 0 : new_flags |= FIF_FCSFAIL;
54 : :
55 [ # # ]: 0 : if (local->fif_plcpfail)
56 : 0 : new_flags |= FIF_PLCPFAIL;
57 : :
58 [ # # ]: 0 : if (local->fif_control)
59 : 0 : new_flags |= FIF_CONTROL;
60 : :
61 [ # # ]: 0 : if (local->fif_other_bss)
62 : 0 : new_flags |= FIF_OTHER_BSS;
63 : :
64 [ # # ]: 0 : if (local->fif_pspoll)
65 : 0 : new_flags |= FIF_PSPOLL;
66 : :
67 : 0 : spin_lock_bh(&local->filter_lock);
68 : 0 : changed_flags = local->filter_flags ^ new_flags;
69 : :
70 : 0 : mc = drv_prepare_multicast(local, &local->mc_list);
71 : 0 : spin_unlock_bh(&local->filter_lock);
72 : :
73 : : /* be a bit nasty */
74 : 0 : new_flags |= (1<<31);
75 : :
76 : 0 : drv_configure_filter(local, changed_flags, &new_flags, mc);
77 : :
78 [ # # ]: 0 : WARN_ON(new_flags & (1<<31));
79 : :
80 : 0 : local->filter_flags = new_flags & ~(1<<31);
81 : 0 : }
82 : :
83 : 0 : static void ieee80211_reconfig_filter(struct work_struct *work)
84 : : {
85 : 0 : struct ieee80211_local *local =
86 : 0 : container_of(work, struct ieee80211_local, reconfig_filter);
87 : :
88 : 0 : ieee80211_configure_filter(local);
89 : 0 : }
90 : :
91 : 0 : static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
92 : : {
93 : 0 : struct ieee80211_sub_if_data *sdata;
94 : 0 : struct cfg80211_chan_def chandef = {};
95 : 0 : u32 changed = 0;
96 : 0 : int power;
97 : 0 : u32 offchannel_flag;
98 : :
99 : 0 : offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
100 : :
101 [ # # ]: 0 : if (local->scan_chandef.chan) {
102 : 0 : chandef = local->scan_chandef;
103 [ # # ]: 0 : } else if (local->tmp_channel) {
104 : 0 : chandef.chan = local->tmp_channel;
105 : 0 : chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
106 : 0 : chandef.center_freq1 = chandef.chan->center_freq;
107 : : } else
108 : 0 : chandef = local->_oper_chandef;
109 : :
110 [ # # ]: 0 : WARN(!cfg80211_chandef_valid(&chandef),
111 : : "control:%d MHz width:%d center: %d/%d MHz",
112 : : chandef.chan->center_freq, chandef.width,
113 : : chandef.center_freq1, chandef.center_freq2);
114 : :
115 [ # # # # ]: 0 : if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
116 : 0 : local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
117 : : else
118 : 0 : local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
119 : :
120 : 0 : offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
121 : :
122 [ # # # # ]: 0 : if (offchannel_flag ||
123 : : !cfg80211_chandef_identical(&local->hw.conf.chandef,
124 : : &local->_oper_chandef)) {
125 : 0 : local->hw.conf.chandef = chandef;
126 : 0 : changed |= IEEE80211_CONF_CHANGE_CHANNEL;
127 : : }
128 : :
129 [ # # ]: 0 : if (!conf_is_ht(&local->hw.conf)) {
130 : : /*
131 : : * mac80211.h documents that this is only valid
132 : : * when the channel is set to an HT type, and
133 : : * that otherwise STATIC is used.
134 : : */
135 : 0 : local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC;
136 [ # # ]: 0 : } else if (local->hw.conf.smps_mode != local->smps_mode) {
137 : 0 : local->hw.conf.smps_mode = local->smps_mode;
138 : 0 : changed |= IEEE80211_CONF_CHANGE_SMPS;
139 : : }
140 : :
141 [ # # # ]: 0 : power = ieee80211_chandef_max_power(&chandef);
142 : :
143 : 0 : rcu_read_lock();
144 [ # # ]: 0 : list_for_each_entry_rcu(sdata, &local->interfaces, list) {
145 [ # # ]: 0 : if (!rcu_access_pointer(sdata->vif.chanctx_conf))
146 : 0 : continue;
147 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
148 : 0 : continue;
149 : 0 : power = min(power, sdata->vif.bss_conf.txpower);
150 : : }
151 : 0 : rcu_read_unlock();
152 : :
153 [ # # ]: 0 : if (local->hw.conf.power_level != power) {
154 : 0 : changed |= IEEE80211_CONF_CHANGE_POWER;
155 : 0 : local->hw.conf.power_level = power;
156 : : }
157 : :
158 : 0 : return changed;
159 : : }
160 : :
161 : 0 : int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
162 : : {
163 : 0 : int ret = 0;
164 : :
165 : 0 : might_sleep();
166 : :
167 [ # # ]: 0 : if (!local->use_chanctx)
168 : 0 : changed |= ieee80211_hw_conf_chan(local);
169 : : else
170 : 0 : changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL |
171 : : IEEE80211_CONF_CHANGE_POWER);
172 : :
173 [ # # # # ]: 0 : if (changed && local->open_count) {
174 : 0 : ret = drv_config(local, changed);
175 : : /*
176 : : * Goal:
177 : : * HW reconfiguration should never fail, the driver has told
178 : : * us what it can support so it should live up to that promise.
179 : : *
180 : : * Current status:
181 : : * rfkill is not integrated with mac80211 and a
182 : : * configuration command can thus fail if hardware rfkill
183 : : * is enabled
184 : : *
185 : : * FIXME: integrate rfkill with mac80211 and then add this
186 : : * WARN_ON() back
187 : : *
188 : : */
189 : : /* WARN_ON(ret); */
190 : : }
191 : :
192 : 0 : return ret;
193 : : }
194 : :
195 : 0 : void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
196 : : u32 changed)
197 : : {
198 : 0 : struct ieee80211_local *local = sdata->local;
199 : :
200 [ # # # # ]: 0 : if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
201 : : return;
202 : :
203 : 0 : drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
204 : : }
205 : :
206 : 0 : u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
207 : : {
208 : 0 : sdata->vif.bss_conf.use_cts_prot = false;
209 : 0 : sdata->vif.bss_conf.use_short_preamble = false;
210 : 0 : sdata->vif.bss_conf.use_short_slot = false;
211 : 0 : return BSS_CHANGED_ERP_CTS_PROT |
212 : : BSS_CHANGED_ERP_PREAMBLE |
213 : : BSS_CHANGED_ERP_SLOT;
214 : : }
215 : :
216 : 0 : static void ieee80211_tasklet_handler(unsigned long data)
217 : : {
218 : 0 : struct ieee80211_local *local = (struct ieee80211_local *) data;
219 : 0 : struct sk_buff *skb;
220 : :
221 [ # # # # ]: 0 : while ((skb = skb_dequeue(&local->skb_queue)) ||
222 : 0 : (skb = skb_dequeue(&local->skb_queue_unreliable))) {
223 [ # # # ]: 0 : switch (skb->pkt_type) {
224 : 0 : case IEEE80211_RX_MSG:
225 : : /* Clear skb->pkt_type in order to not confuse kernel
226 : : * netstack. */
227 : 0 : skb->pkt_type = 0;
228 : 0 : ieee80211_rx(&local->hw, skb);
229 : : break;
230 : 0 : case IEEE80211_TX_STATUS_MSG:
231 : 0 : skb->pkt_type = 0;
232 : 0 : ieee80211_tx_status(&local->hw, skb);
233 : 0 : break;
234 : : default:
235 : 0 : WARN(1, "mac80211: Packet is of unknown type %d\n",
236 : : skb->pkt_type);
237 : 0 : dev_kfree_skb(skb);
238 : 0 : break;
239 : : }
240 : : }
241 : 0 : }
242 : :
243 : 0 : static void ieee80211_restart_work(struct work_struct *work)
244 : : {
245 : 0 : struct ieee80211_local *local =
246 : 0 : container_of(work, struct ieee80211_local, restart_work);
247 : 0 : struct ieee80211_sub_if_data *sdata;
248 : :
249 : : /* wait for scan work complete */
250 : 0 : flush_workqueue(local->workqueue);
251 : 0 : flush_work(&local->sched_scan_stopped_work);
252 : :
253 [ # # ]: 0 : WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
254 : : "%s called with hardware scan in progress\n", __func__);
255 : :
256 : 0 : flush_work(&local->radar_detected_work);
257 : 0 : rtnl_lock();
258 [ # # ]: 0 : list_for_each_entry(sdata, &local->interfaces, list) {
259 : : /*
260 : : * XXX: there may be more work for other vif types and even
261 : : * for station mode: a good thing would be to run most of
262 : : * the iface type's dependent _stop (ieee80211_mg_stop,
263 : : * ieee80211_ibss_stop) etc...
264 : : * For now, fix only the specific bug that was seen: race
265 : : * between csa_connection_drop_work and us.
266 : : */
267 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_STATION) {
268 : : /*
269 : : * This worker is scheduled from the iface worker that
270 : : * runs on mac80211's workqueue, so we can't be
271 : : * scheduling this worker after the cancel right here.
272 : : * The exception is ieee80211_chswitch_done.
273 : : * Then we can have a race...
274 : : */
275 : 0 : cancel_work_sync(&sdata->u.mgd.csa_connection_drop_work);
276 : : }
277 : 0 : flush_delayed_work(&sdata->dec_tailroom_needed_wk);
278 : : }
279 : 0 : ieee80211_scan_cancel(local);
280 : :
281 : : /* make sure any new ROC will consider local->in_reconfig */
282 : 0 : flush_delayed_work(&local->roc_work);
283 : 0 : flush_work(&local->hw_roc_done);
284 : :
285 : : /* wait for all packet processing to be done */
286 : 0 : synchronize_net();
287 : :
288 : 0 : ieee80211_reconfig(local);
289 : 0 : rtnl_unlock();
290 : 0 : }
291 : :
292 : 0 : void ieee80211_restart_hw(struct ieee80211_hw *hw)
293 : : {
294 : 0 : struct ieee80211_local *local = hw_to_local(hw);
295 : :
296 : 0 : trace_api_restart_hw(local);
297 : :
298 : 0 : wiphy_info(hw->wiphy,
299 : : "Hardware restart was requested\n");
300 : :
301 : : /* use this reason, ieee80211_reconfig will unblock it */
302 : 0 : ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
303 : : IEEE80211_QUEUE_STOP_REASON_SUSPEND,
304 : : false);
305 : :
306 : : /*
307 : : * Stop all Rx during the reconfig. We don't want state changes
308 : : * or driver callbacks while this is in progress.
309 : : */
310 : 0 : local->in_reconfig = true;
311 : 0 : barrier();
312 : :
313 : 0 : queue_work(system_freezable_wq, &local->restart_work);
314 : 0 : }
315 : : EXPORT_SYMBOL(ieee80211_restart_hw);
316 : :
317 : : #ifdef CONFIG_INET
318 : 0 : static int ieee80211_ifa_changed(struct notifier_block *nb,
319 : : unsigned long data, void *arg)
320 : : {
321 : 0 : struct in_ifaddr *ifa = arg;
322 : 0 : struct ieee80211_local *local =
323 : 0 : container_of(nb, struct ieee80211_local,
324 : : ifa_notifier);
325 : 0 : struct net_device *ndev = ifa->ifa_dev->dev;
326 : 0 : struct wireless_dev *wdev = ndev->ieee80211_ptr;
327 : 0 : struct in_device *idev;
328 : 0 : struct ieee80211_sub_if_data *sdata;
329 : 0 : struct ieee80211_bss_conf *bss_conf;
330 : 0 : struct ieee80211_if_managed *ifmgd;
331 : 0 : int c = 0;
332 : :
333 : : /* Make sure it's our interface that got changed */
334 [ # # ]: 0 : if (!wdev)
335 : : return NOTIFY_DONE;
336 : :
337 [ # # ]: 0 : if (wdev->wiphy != local->hw.wiphy)
338 : : return NOTIFY_DONE;
339 : :
340 [ # # ]: 0 : sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
341 : 0 : bss_conf = &sdata->vif.bss_conf;
342 : :
343 : : /* ARP filtering is only supported in managed mode */
344 [ # # ]: 0 : if (sdata->vif.type != NL80211_IFTYPE_STATION)
345 : : return NOTIFY_DONE;
346 : :
347 [ # # ]: 0 : idev = __in_dev_get_rtnl(sdata->dev);
348 [ # # ]: 0 : if (!idev)
349 : : return NOTIFY_DONE;
350 : :
351 : 0 : ifmgd = &sdata->u.mgd;
352 : 0 : sdata_lock(sdata);
353 : :
354 : : /* Copy the addresses to the bss_conf list */
355 : 0 : ifa = rtnl_dereference(idev->ifa_list);
356 [ # # ]: 0 : while (ifa) {
357 [ # # ]: 0 : if (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN)
358 : 0 : bss_conf->arp_addr_list[c] = ifa->ifa_address;
359 : 0 : ifa = rtnl_dereference(ifa->ifa_next);
360 : 0 : c++;
361 : : }
362 : :
363 : 0 : bss_conf->arp_addr_cnt = c;
364 : :
365 : : /* Configure driver only if associated (which also implies it is up) */
366 [ # # ]: 0 : if (ifmgd->associated)
367 [ # # ]: 0 : ieee80211_bss_info_change_notify(sdata,
368 : : BSS_CHANGED_ARP_FILTER);
369 : :
370 : 0 : sdata_unlock(sdata);
371 : :
372 : 0 : return NOTIFY_OK;
373 : : }
374 : : #endif
375 : :
376 : : #if IS_ENABLED(CONFIG_IPV6)
377 : 0 : static int ieee80211_ifa6_changed(struct notifier_block *nb,
378 : : unsigned long data, void *arg)
379 : : {
380 : 0 : struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
381 : 0 : struct inet6_dev *idev = ifa->idev;
382 : 0 : struct net_device *ndev = ifa->idev->dev;
383 : 0 : struct ieee80211_local *local =
384 : 0 : container_of(nb, struct ieee80211_local, ifa6_notifier);
385 : 0 : struct wireless_dev *wdev = ndev->ieee80211_ptr;
386 : 0 : struct ieee80211_sub_if_data *sdata;
387 : :
388 : : /* Make sure it's our interface that got changed */
389 [ # # # # ]: 0 : if (!wdev || wdev->wiphy != local->hw.wiphy)
390 : : return NOTIFY_DONE;
391 : :
392 [ # # ]: 0 : sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
393 : :
394 : : /*
395 : : * For now only support station mode. This is mostly because
396 : : * doing AP would have to handle AP_VLAN in some way ...
397 : : */
398 [ # # ]: 0 : if (sdata->vif.type != NL80211_IFTYPE_STATION)
399 : : return NOTIFY_DONE;
400 : :
401 : 0 : drv_ipv6_addr_change(local, sdata, idev);
402 : :
403 : 0 : return NOTIFY_OK;
404 : : }
405 : : #endif
406 : :
407 : : /* There isn't a lot of sense in it, but you can transmit anything you like */
408 : : static const struct ieee80211_txrx_stypes
409 : : ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
410 : : [NL80211_IFTYPE_ADHOC] = {
411 : : .tx = 0xffff,
412 : : .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
413 : : BIT(IEEE80211_STYPE_AUTH >> 4) |
414 : : BIT(IEEE80211_STYPE_DEAUTH >> 4) |
415 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
416 : : },
417 : : [NL80211_IFTYPE_STATION] = {
418 : : .tx = 0xffff,
419 : : .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
420 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
421 : : },
422 : : [NL80211_IFTYPE_AP] = {
423 : : .tx = 0xffff,
424 : : .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
425 : : BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
426 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
427 : : BIT(IEEE80211_STYPE_DISASSOC >> 4) |
428 : : BIT(IEEE80211_STYPE_AUTH >> 4) |
429 : : BIT(IEEE80211_STYPE_DEAUTH >> 4) |
430 : : BIT(IEEE80211_STYPE_ACTION >> 4),
431 : : },
432 : : [NL80211_IFTYPE_AP_VLAN] = {
433 : : /* copy AP */
434 : : .tx = 0xffff,
435 : : .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
436 : : BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
437 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
438 : : BIT(IEEE80211_STYPE_DISASSOC >> 4) |
439 : : BIT(IEEE80211_STYPE_AUTH >> 4) |
440 : : BIT(IEEE80211_STYPE_DEAUTH >> 4) |
441 : : BIT(IEEE80211_STYPE_ACTION >> 4),
442 : : },
443 : : [NL80211_IFTYPE_P2P_CLIENT] = {
444 : : .tx = 0xffff,
445 : : .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
446 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
447 : : },
448 : : [NL80211_IFTYPE_P2P_GO] = {
449 : : .tx = 0xffff,
450 : : .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
451 : : BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
452 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
453 : : BIT(IEEE80211_STYPE_DISASSOC >> 4) |
454 : : BIT(IEEE80211_STYPE_AUTH >> 4) |
455 : : BIT(IEEE80211_STYPE_DEAUTH >> 4) |
456 : : BIT(IEEE80211_STYPE_ACTION >> 4),
457 : : },
458 : : [NL80211_IFTYPE_MESH_POINT] = {
459 : : .tx = 0xffff,
460 : : .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
461 : : BIT(IEEE80211_STYPE_AUTH >> 4) |
462 : : BIT(IEEE80211_STYPE_DEAUTH >> 4),
463 : : },
464 : : [NL80211_IFTYPE_P2P_DEVICE] = {
465 : : .tx = 0xffff,
466 : : .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
467 : : BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
468 : : },
469 : : };
470 : :
471 : : static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
472 : : .ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR |
473 : : IEEE80211_HT_AMPDU_PARM_DENSITY,
474 : :
475 : : .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
476 : : IEEE80211_HT_CAP_MAX_AMSDU |
477 : : IEEE80211_HT_CAP_SGI_20 |
478 : : IEEE80211_HT_CAP_SGI_40 |
479 : : IEEE80211_HT_CAP_TX_STBC |
480 : : IEEE80211_HT_CAP_RX_STBC |
481 : : IEEE80211_HT_CAP_LDPC_CODING |
482 : : IEEE80211_HT_CAP_40MHZ_INTOLERANT),
483 : : .mcs = {
484 : : .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
485 : : 0xff, 0xff, 0xff, 0xff, 0xff, },
486 : : },
487 : : };
488 : :
489 : : static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = {
490 : : .vht_cap_info =
491 : : cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC |
492 : : IEEE80211_VHT_CAP_SHORT_GI_80 |
493 : : IEEE80211_VHT_CAP_SHORT_GI_160 |
494 : : IEEE80211_VHT_CAP_RXSTBC_MASK |
495 : : IEEE80211_VHT_CAP_TXSTBC |
496 : : IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
497 : : IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
498 : : IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
499 : : IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
500 : : IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK),
501 : : .supp_mcs = {
502 : : .rx_mcs_map = cpu_to_le16(~0),
503 : : .tx_mcs_map = cpu_to_le16(~0),
504 : : },
505 : : };
506 : :
507 : 0 : struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
508 : : const struct ieee80211_ops *ops,
509 : : const char *requested_name)
510 : : {
511 : 0 : struct ieee80211_local *local;
512 : 0 : int priv_size, i;
513 : 0 : struct wiphy *wiphy;
514 : 0 : bool use_chanctx;
515 : :
516 [ # # # # : 0 : if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
# # # # #
# # # # #
# # # # ]
517 : : !ops->add_interface || !ops->remove_interface ||
518 : : !ops->configure_filter))
519 : : return NULL;
520 : :
521 [ # # # # : 0 : if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
# # # # #
# ]
522 : : return NULL;
523 : :
524 : : /* check all or no channel context operations exist */
525 : 0 : i = !!ops->add_chanctx + !!ops->remove_chanctx +
526 : 0 : !!ops->change_chanctx + !!ops->assign_vif_chanctx +
527 : 0 : !!ops->unassign_vif_chanctx;
528 [ # # # # ]: 0 : if (WARN_ON(i != 0 && i != 5))
529 : : return NULL;
530 : 0 : use_chanctx = i == 5;
531 : :
532 : : /* Ensure 32-byte alignment of our private data and hw private data.
533 : : * We use the wiphy priv data for both our ieee80211_local and for
534 : : * the driver's private data
535 : : *
536 : : * In memory it'll be like this:
537 : : *
538 : : * +-------------------------+
539 : : * | struct wiphy |
540 : : * +-------------------------+
541 : : * | struct ieee80211_local |
542 : : * +-------------------------+
543 : : * | driver's private data |
544 : : * +-------------------------+
545 : : *
546 : : */
547 : 0 : priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
548 : :
549 : 0 : wiphy = wiphy_new_nm(&mac80211_config_ops, priv_size, requested_name);
550 : :
551 [ # # ]: 0 : if (!wiphy)
552 : : return NULL;
553 : :
554 : 0 : wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
555 : :
556 : 0 : wiphy->privid = mac80211_wiphy_privid;
557 : :
558 : 0 : wiphy->flags |= WIPHY_FLAG_NETNS_OK |
559 : : WIPHY_FLAG_4ADDR_AP |
560 : : WIPHY_FLAG_4ADDR_STATION |
561 : : WIPHY_FLAG_REPORTS_OBSS |
562 : : WIPHY_FLAG_OFFCHAN_TX;
563 : :
564 [ # # ]: 0 : if (ops->remain_on_channel)
565 : 0 : wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
566 : :
567 : 0 : wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
568 : : NL80211_FEATURE_SAE |
569 : : NL80211_FEATURE_HT_IBSS |
570 : : NL80211_FEATURE_VIF_TXPOWER |
571 : : NL80211_FEATURE_MAC_ON_CREATE |
572 : : NL80211_FEATURE_USERSPACE_MPM |
573 : : NL80211_FEATURE_FULL_AP_CLIENT_STATE;
574 [ # # ]: 0 : wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
575 : 0 : wiphy_ext_feature_set(wiphy,
576 : : NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
577 : :
578 [ # # ]: 0 : if (!ops->hw_scan) {
579 : 0 : wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
580 : : NL80211_FEATURE_AP_SCAN;
581 : : /*
582 : : * if the driver behaves correctly using the probe request
583 : : * (template) from mac80211, then both of these should be
584 : : * supported even with hw scan - but let drivers opt in.
585 : : */
586 : 0 : wiphy_ext_feature_set(wiphy,
587 : : NL80211_EXT_FEATURE_SCAN_RANDOM_SN);
588 : 0 : wiphy_ext_feature_set(wiphy,
589 : : NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT);
590 : : }
591 : :
592 [ # # ]: 0 : if (!ops->set_key)
593 : 0 : wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
594 : :
595 [ # # ]: 0 : if (ops->wake_tx_queue)
596 : 0 : wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
597 : :
598 : 0 : wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
599 : :
600 : 0 : wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
601 : :
602 : 0 : local = wiphy_priv(wiphy);
603 : :
604 [ # # ]: 0 : if (sta_info_init(local))
605 : 0 : goto err_free;
606 : :
607 : 0 : local->hw.wiphy = wiphy;
608 : :
609 : 0 : local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
610 : :
611 : 0 : local->ops = ops;
612 : 0 : local->use_chanctx = use_chanctx;
613 : :
614 : : /*
615 : : * We need a bit of data queued to build aggregates properly, so
616 : : * instruct the TCP stack to allow more than a single ms of data
617 : : * to be queued in the stack. The value is a bit-shift of 1
618 : : * second, so 7 is ~8ms of queued data. Only affects local TCP
619 : : * sockets.
620 : : * This is the default, anyhow - drivers may need to override it
621 : : * for local reasons (longer buffers, longer completion time, or
622 : : * similar).
623 : : */
624 : 0 : local->hw.tx_sk_pacing_shift = 7;
625 : :
626 : : /* set up some defaults */
627 : 0 : local->hw.queues = 1;
628 : 0 : local->hw.max_rates = 1;
629 : 0 : local->hw.max_report_rates = 0;
630 : 0 : local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HT;
631 : 0 : local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HT;
632 : 0 : local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE;
633 : 0 : local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
634 : 0 : local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
635 : 0 : local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
636 : : IEEE80211_RADIOTAP_MCS_HAVE_GI |
637 : : IEEE80211_RADIOTAP_MCS_HAVE_BW;
638 : 0 : local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
639 : : IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
640 : 0 : local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
641 : 0 : local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
642 : 0 : local->hw.max_mtu = IEEE80211_MAX_DATA_LEN;
643 : 0 : local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
644 : 0 : wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
645 : 0 : wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
646 : :
647 : 0 : local->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF;
648 : :
649 : 0 : wiphy->extended_capabilities = local->ext_capa;
650 : 0 : wiphy->extended_capabilities_mask = local->ext_capa;
651 : 0 : wiphy->extended_capabilities_len =
652 : : ARRAY_SIZE(local->ext_capa);
653 : :
654 : 0 : INIT_LIST_HEAD(&local->interfaces);
655 : 0 : INIT_LIST_HEAD(&local->mon_list);
656 : :
657 : 0 : __hw_addr_init(&local->mc_list);
658 : :
659 : 0 : mutex_init(&local->iflist_mtx);
660 : 0 : mutex_init(&local->mtx);
661 : :
662 : 0 : mutex_init(&local->key_mtx);
663 : 0 : spin_lock_init(&local->filter_lock);
664 : 0 : spin_lock_init(&local->rx_path_lock);
665 : 0 : spin_lock_init(&local->queue_stop_reason_lock);
666 : :
667 [ # # ]: 0 : for (i = 0; i < IEEE80211_NUM_ACS; i++) {
668 : 0 : INIT_LIST_HEAD(&local->active_txqs[i]);
669 : 0 : spin_lock_init(&local->active_txq_lock[i]);
670 : 0 : local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
671 : 0 : local->aql_txq_limit_high[i] =
672 : : IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
673 : : }
674 : :
675 : 0 : local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
676 : 0 : local->aql_threshold = IEEE80211_AQL_THRESHOLD;
677 : 0 : atomic_set(&local->aql_total_pending_airtime, 0);
678 : :
679 : 0 : INIT_LIST_HEAD(&local->chanctx_list);
680 : 0 : mutex_init(&local->chanctx_mtx);
681 : :
682 : 0 : INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
683 : :
684 : 0 : INIT_WORK(&local->restart_work, ieee80211_restart_work);
685 : :
686 : 0 : INIT_WORK(&local->radar_detected_work,
687 : : ieee80211_dfs_radar_detected_work);
688 : :
689 : 0 : INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
690 : 0 : local->smps_mode = IEEE80211_SMPS_OFF;
691 : :
692 : 0 : INIT_WORK(&local->dynamic_ps_enable_work,
693 : : ieee80211_dynamic_ps_enable_work);
694 : 0 : INIT_WORK(&local->dynamic_ps_disable_work,
695 : : ieee80211_dynamic_ps_disable_work);
696 : 0 : timer_setup(&local->dynamic_ps_timer, ieee80211_dynamic_ps_timer, 0);
697 : :
698 : 0 : INIT_WORK(&local->sched_scan_stopped_work,
699 : : ieee80211_sched_scan_stopped_work);
700 : :
701 : 0 : INIT_WORK(&local->tdls_chsw_work, ieee80211_tdls_chsw_work);
702 : :
703 : 0 : spin_lock_init(&local->ack_status_lock);
704 : 0 : idr_init(&local->ack_status_frames);
705 : :
706 [ # # ]: 0 : for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
707 : 0 : skb_queue_head_init(&local->pending[i]);
708 : 0 : atomic_set(&local->agg_queue_stop[i], 0);
709 : : }
710 : 0 : tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
711 : : (unsigned long)local);
712 : :
713 [ # # ]: 0 : if (ops->wake_tx_queue)
714 : 0 : tasklet_init(&local->wake_txqs_tasklet, ieee80211_wake_txqs,
715 : : (unsigned long)local);
716 : :
717 : 0 : tasklet_init(&local->tasklet,
718 : : ieee80211_tasklet_handler,
719 : : (unsigned long) local);
720 : :
721 : 0 : skb_queue_head_init(&local->skb_queue);
722 : 0 : skb_queue_head_init(&local->skb_queue_unreliable);
723 : 0 : skb_queue_head_init(&local->skb_queue_tdls_chsw);
724 : :
725 : 0 : ieee80211_alloc_led_names(local);
726 : :
727 : 0 : ieee80211_roc_setup(local);
728 : :
729 : 0 : local->hw.radiotap_timestamp.units_pos = -1;
730 : 0 : local->hw.radiotap_timestamp.accuracy = -1;
731 : :
732 : 0 : return &local->hw;
733 : : err_free:
734 : 0 : wiphy_free(wiphy);
735 : 0 : return NULL;
736 : : }
737 : : EXPORT_SYMBOL(ieee80211_alloc_hw_nm);
738 : :
739 : 0 : static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
740 : : {
741 : 0 : bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */
742 : 0 : bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE);
743 : 0 : int n_suites = 0, r = 0, w = 0;
744 : 0 : u32 *suites;
745 : 0 : static const u32 cipher_suites[] = {
746 : : /* keep WEP first, it may be removed below */
747 : : WLAN_CIPHER_SUITE_WEP40,
748 : : WLAN_CIPHER_SUITE_WEP104,
749 : : WLAN_CIPHER_SUITE_TKIP,
750 : : WLAN_CIPHER_SUITE_CCMP,
751 : : WLAN_CIPHER_SUITE_CCMP_256,
752 : : WLAN_CIPHER_SUITE_GCMP,
753 : : WLAN_CIPHER_SUITE_GCMP_256,
754 : :
755 : : /* keep last -- depends on hw flags! */
756 : : WLAN_CIPHER_SUITE_AES_CMAC,
757 : : WLAN_CIPHER_SUITE_BIP_CMAC_256,
758 : : WLAN_CIPHER_SUITE_BIP_GMAC_128,
759 : : WLAN_CIPHER_SUITE_BIP_GMAC_256,
760 : : };
761 : :
762 [ # # ]: 0 : if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) ||
763 [ # # ]: 0 : local->hw.wiphy->cipher_suites) {
764 : : /* If the driver advertises, or doesn't support SW crypto,
765 : : * we only need to remove WEP if necessary.
766 : : */
767 : : if (have_wep)
768 : : return 0;
769 : :
770 : : /* well if it has _no_ ciphers ... fine */
771 : : if (!local->hw.wiphy->n_cipher_suites)
772 : : return 0;
773 : :
774 : : /* Driver provides cipher suites, but we need to exclude WEP */
775 : : suites = kmemdup(local->hw.wiphy->cipher_suites,
776 : : sizeof(u32) * local->hw.wiphy->n_cipher_suites,
777 : : GFP_KERNEL);
778 : : if (!suites)
779 : : return -ENOMEM;
780 : :
781 : : for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
782 : : u32 suite = local->hw.wiphy->cipher_suites[r];
783 : :
784 : : if (suite == WLAN_CIPHER_SUITE_WEP40 ||
785 : : suite == WLAN_CIPHER_SUITE_WEP104)
786 : : continue;
787 : : suites[w++] = suite;
788 : : }
789 [ # # ]: 0 : } else if (!local->hw.cipher_schemes) {
790 : : /* If the driver doesn't have cipher schemes, there's nothing
791 : : * else to do other than assign the (software supported and
792 : : * perhaps offloaded) cipher suites.
793 : : */
794 : 0 : local->hw.wiphy->cipher_suites = cipher_suites;
795 : 0 : local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
796 : :
797 [ # # ]: 0 : if (!have_mfp)
798 : 0 : local->hw.wiphy->n_cipher_suites -= 4;
799 : :
800 : 0 : if (!have_wep) {
801 : : local->hw.wiphy->cipher_suites += 2;
802 : : local->hw.wiphy->n_cipher_suites -= 2;
803 : : }
804 : :
805 : : /* not dynamically allocated, so just return */
806 : 0 : return 0;
807 : : } else {
808 : 0 : const struct ieee80211_cipher_scheme *cs;
809 : :
810 : 0 : cs = local->hw.cipher_schemes;
811 : :
812 : : /* Driver specifies cipher schemes only (but not cipher suites
813 : : * including the schemes)
814 : : *
815 : : * We start counting ciphers defined by schemes, TKIP, CCMP,
816 : : * CCMP-256, GCMP, and GCMP-256
817 : : */
818 : 0 : n_suites = local->hw.n_cipher_schemes + 5;
819 : :
820 : : /* check if we have WEP40 and WEP104 */
821 : 0 : if (have_wep)
822 : 0 : n_suites += 2;
823 : :
824 : : /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128,
825 : : * BIP-GMAC-256
826 : : */
827 [ # # ]: 0 : if (have_mfp)
828 : 0 : n_suites += 4;
829 : :
830 : 0 : suites = kmalloc_array(n_suites, sizeof(u32), GFP_KERNEL);
831 [ # # ]: 0 : if (!suites)
832 : : return -ENOMEM;
833 : :
834 : 0 : suites[w++] = WLAN_CIPHER_SUITE_CCMP;
835 : 0 : suites[w++] = WLAN_CIPHER_SUITE_CCMP_256;
836 : 0 : suites[w++] = WLAN_CIPHER_SUITE_TKIP;
837 : 0 : suites[w++] = WLAN_CIPHER_SUITE_GCMP;
838 : 0 : suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
839 : :
840 : 0 : if (have_wep) {
841 : 0 : suites[w++] = WLAN_CIPHER_SUITE_WEP40;
842 : 0 : suites[w++] = WLAN_CIPHER_SUITE_WEP104;
843 : : }
844 : :
845 [ # # ]: 0 : if (have_mfp) {
846 : 0 : suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
847 : 0 : suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256;
848 : 0 : suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128;
849 : 0 : suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256;
850 : : }
851 : :
852 [ # # ]: 0 : for (r = 0; r < local->hw.n_cipher_schemes; r++) {
853 : 0 : suites[w++] = cs[r].cipher;
854 [ # # # # ]: 0 : if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) {
855 : 0 : kfree(suites);
856 : 0 : return -EINVAL;
857 : : }
858 : : }
859 : : }
860 : :
861 : 0 : local->hw.wiphy->cipher_suites = suites;
862 : 0 : local->hw.wiphy->n_cipher_suites = w;
863 : 0 : local->wiphy_ciphers_allocated = true;
864 : :
865 : 0 : return 0;
866 : : }
867 : :
868 : 0 : int ieee80211_register_hw(struct ieee80211_hw *hw)
869 : : {
870 : 0 : struct ieee80211_local *local = hw_to_local(hw);
871 : 0 : int result, i;
872 : 0 : enum nl80211_band band;
873 : 0 : int channels, max_bitrates;
874 : 0 : bool supp_ht, supp_vht, supp_he;
875 : 0 : netdev_features_t feature_whitelist;
876 : 0 : struct cfg80211_chan_def dflt_chandef = {};
877 : :
878 [ # # ]: 0 : if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
879 [ # # ]: 0 : (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
880 [ # # ]: 0 : local->hw.offchannel_tx_hw_queue >= local->hw.queues))
881 : : return -EINVAL;
882 : :
883 [ # # ]: 0 : if ((hw->wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
884 [ # # ]: 0 : (!local->ops->tdls_channel_switch ||
885 [ # # ]: 0 : !local->ops->tdls_cancel_channel_switch ||
886 [ # # ]: 0 : !local->ops->tdls_recv_channel_switch))
887 : : return -EOPNOTSUPP;
888 : :
889 [ # # # # : 0 : if (WARN_ON(ieee80211_hw_check(hw, SUPPORTS_TX_FRAG) &&
# # # # ]
890 : : !local->ops->set_frag_threshold))
891 : : return -EINVAL;
892 : :
893 [ # # # # : 0 : if (WARN_ON(local->hw.wiphy->interface_modes &
# # # # #
# ]
894 : : BIT(NL80211_IFTYPE_NAN) &&
895 : : (!local->ops->start_nan || !local->ops->stop_nan)))
896 : : return -EINVAL;
897 : :
898 : : #ifdef CONFIG_PM
899 [ # # # # : 0 : if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
# # ]
900 : : return -EINVAL;
901 : : #endif
902 : :
903 [ # # ]: 0 : if (!local->use_chanctx) {
904 [ # # ]: 0 : for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
905 : 0 : const struct ieee80211_iface_combination *comb;
906 : :
907 : 0 : comb = &local->hw.wiphy->iface_combinations[i];
908 : :
909 [ # # ]: 0 : if (comb->num_different_channels > 1)
910 : : return -EINVAL;
911 : : }
912 : : } else {
913 : : /*
914 : : * WDS is currently prohibited when channel contexts are used
915 : : * because there's no clear definition of which channel WDS
916 : : * type interfaces use
917 : : */
918 [ # # ]: 0 : if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
919 : : return -EINVAL;
920 : :
921 : : /* DFS is not supported with multi-channel combinations yet */
922 [ # # ]: 0 : for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
923 : 0 : const struct ieee80211_iface_combination *comb;
924 : :
925 : 0 : comb = &local->hw.wiphy->iface_combinations[i];
926 : :
927 [ # # ]: 0 : if (comb->radar_detect_widths &&
928 [ # # ]: 0 : comb->num_different_channels > 1)
929 : : return -EINVAL;
930 : : }
931 : : }
932 : :
933 : : /* Only HW csum features are currently compatible with mac80211 */
934 : 0 : feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
935 : : NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA |
936 : : NETIF_F_GSO_SOFTWARE | NETIF_F_RXCSUM;
937 [ # # # # ]: 0 : if (WARN_ON(hw->netdev_features & ~feature_whitelist))
938 : : return -EINVAL;
939 : :
940 [ # # ]: 0 : if (hw->max_report_rates == 0)
941 : 0 : hw->max_report_rates = hw->max_rates;
942 : :
943 : 0 : local->rx_chains = 1;
944 : :
945 : : /*
946 : : * generic code guarantees at least one band,
947 : : * set this very early because much code assumes
948 : : * that hw.conf.channel is assigned
949 : : */
950 : 0 : channels = 0;
951 : 0 : max_bitrates = 0;
952 : 0 : supp_ht = false;
953 : 0 : supp_vht = false;
954 : 0 : supp_he = false;
955 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++) {
956 : 0 : struct ieee80211_supported_band *sband;
957 : :
958 : 0 : sband = local->hw.wiphy->bands[band];
959 [ # # ]: 0 : if (!sband)
960 : 0 : continue;
961 : :
962 [ # # ]: 0 : if (!dflt_chandef.chan) {
963 : 0 : cfg80211_chandef_create(&dflt_chandef,
964 : : &sband->channels[0],
965 : : NL80211_CHAN_NO_HT);
966 : : /* init channel we're on */
967 [ # # # # ]: 0 : if (!local->use_chanctx && !local->_oper_chandef.chan) {
968 : 0 : local->hw.conf.chandef = dflt_chandef;
969 : 0 : local->_oper_chandef = dflt_chandef;
970 : : }
971 : 0 : local->monitor_chandef = dflt_chandef;
972 : : }
973 : :
974 : 0 : channels += sband->n_channels;
975 : :
976 : 0 : if (max_bitrates < sband->n_bitrates)
977 : : max_bitrates = sband->n_bitrates;
978 [ # # # # ]: 0 : supp_ht = supp_ht || sband->ht_cap.ht_supported;
979 [ # # # # ]: 0 : supp_vht = supp_vht || sband->vht_cap.vht_supported;
980 : :
981 [ # # ]: 0 : if (!supp_he)
982 : 0 : supp_he = !!ieee80211_get_he_sta_cap(sband);
983 : :
984 [ # # ]: 0 : if (!sband->ht_cap.ht_supported)
985 : 0 : continue;
986 : :
987 : : /* TODO: consider VHT for RX chains, hopefully it's the same */
988 : 0 : local->rx_chains =
989 : 0 : max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
990 : : local->rx_chains);
991 : :
992 : : /* no need to mask, SM_PS_DISABLED has all bits set */
993 : 0 : sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
994 : : IEEE80211_HT_CAP_SM_PS_SHIFT;
995 : : }
996 : :
997 : : /* if low-level driver supports AP, we also support VLAN.
998 : : * drivers advertising SW_CRYPTO_CONTROL should enable AP_VLAN
999 : : * based on their support to transmit SW encrypted packets.
1000 : : */
1001 [ # # # # ]: 0 : if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP) &&
1002 : : !ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL)) {
1003 : 0 : hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
1004 : 0 : hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
1005 : : }
1006 : :
1007 : : /* mac80211 always supports monitor */
1008 : 0 : hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
1009 : 0 : hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
1010 : :
1011 : : /* mac80211 doesn't support more than one IBSS interface right now */
1012 [ # # ]: 0 : for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
1013 : 0 : const struct ieee80211_iface_combination *c;
1014 : 0 : int j;
1015 : :
1016 : 0 : c = &hw->wiphy->iface_combinations[i];
1017 : :
1018 [ # # ]: 0 : for (j = 0; j < c->n_limits; j++)
1019 [ # # ]: 0 : if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
1020 [ # # ]: 0 : c->limits[j].max > 1)
1021 : : return -EINVAL;
1022 : : }
1023 : :
1024 : 0 : local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
1025 : : sizeof(void *) * channels, GFP_KERNEL);
1026 [ # # ]: 0 : if (!local->int_scan_req)
1027 : : return -ENOMEM;
1028 : :
1029 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++) {
1030 [ # # ]: 0 : if (!local->hw.wiphy->bands[band])
1031 : 0 : continue;
1032 : 0 : local->int_scan_req->rates[band] = (u32) -1;
1033 : : }
1034 : :
1035 : : #ifndef CONFIG_MAC80211_MESH
1036 : : /* mesh depends on Kconfig, but drivers should set it if they want */
1037 : 0 : local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
1038 : : #endif
1039 : :
1040 : : /* if the underlying driver supports mesh, mac80211 will (at least)
1041 : : * provide routing of mesh authentication frames to userspace */
1042 [ # # ]: 0 : if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
1043 : 0 : local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
1044 : :
1045 : : /* mac80211 supports control port protocol changing */
1046 : 0 : local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
1047 : :
1048 [ # # ]: 0 : if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) {
1049 : 0 : local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
1050 [ # # ]: 0 : } else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) {
1051 : 0 : local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
1052 [ # # ]: 0 : if (hw->max_signal <= 0) {
1053 : 0 : result = -EINVAL;
1054 : 0 : goto fail_wiphy_register;
1055 : : }
1056 : : }
1057 : :
1058 : : /* Mac80211 and therefore all drivers using SW crypto only
1059 : : * are able to handle PTK rekeys and Extended Key ID.
1060 : : */
1061 [ # # ]: 0 : if (!local->ops->set_key) {
1062 : 0 : wiphy_ext_feature_set(local->hw.wiphy,
1063 : : NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
1064 : 0 : wiphy_ext_feature_set(local->hw.wiphy,
1065 : : NL80211_EXT_FEATURE_EXT_KEY_ID);
1066 : : }
1067 : :
1068 : : /*
1069 : : * Calculate scan IE length -- we need this to alloc
1070 : : * memory and to subtract from the driver limit. It
1071 : : * includes the DS Params, (extended) supported rates, and HT
1072 : : * information -- SSID is the driver's responsibility.
1073 : : */
1074 : 0 : local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
1075 : : 3 /* DS Params */;
1076 [ # # ]: 0 : if (supp_ht)
1077 : 0 : local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
1078 : :
1079 [ # # ]: 0 : if (supp_vht)
1080 : 0 : local->scan_ies_len +=
1081 : : 2 + sizeof(struct ieee80211_vht_cap);
1082 : :
1083 : : /* HE cap element is variable in size - set len to allow max size */
1084 : : /*
1085 : : * TODO: 1 is added at the end of the calculation to accommodate for
1086 : : * the temporary placing of the HE capabilities IE under EXT.
1087 : : * Remove it once it is placed in the final place.
1088 : : */
1089 [ # # ]: 0 : if (supp_he)
1090 : 0 : local->scan_ies_len +=
1091 : : 2 + sizeof(struct ieee80211_he_cap_elem) +
1092 : : sizeof(struct ieee80211_he_mcs_nss_supp) +
1093 : : IEEE80211_HE_PPE_THRES_MAX_LEN + 1;
1094 : :
1095 [ # # ]: 0 : if (!local->ops->hw_scan) {
1096 : : /* For hw_scan, driver needs to set these up. */
1097 : 0 : local->hw.wiphy->max_scan_ssids = 4;
1098 : 0 : local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
1099 : : }
1100 : :
1101 : : /*
1102 : : * If the driver supports any scan IEs, then assume the
1103 : : * limit includes the IEs mac80211 will add, otherwise
1104 : : * leave it at zero and let the driver sort it out; we
1105 : : * still pass our IEs to the driver but userspace will
1106 : : * not be allowed to in that case.
1107 : : */
1108 [ # # ]: 0 : if (local->hw.wiphy->max_scan_ie_len)
1109 : 0 : local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
1110 : :
1111 [ # # ]: 0 : WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes,
1112 : : local->hw.n_cipher_schemes));
1113 : :
1114 : 0 : result = ieee80211_init_cipher_suites(local);
1115 [ # # ]: 0 : if (result < 0)
1116 : 0 : goto fail_wiphy_register;
1117 : :
1118 [ # # ]: 0 : if (!local->ops->remain_on_channel)
1119 : 0 : local->hw.wiphy->max_remain_on_channel_duration = 5000;
1120 : :
1121 : : /* mac80211 based drivers don't support internal TDLS setup */
1122 [ # # ]: 0 : if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
1123 : 0 : local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
1124 : :
1125 : : /* mac80211 supports eCSA, if the driver supports STA CSA at all */
1126 [ # # ]: 0 : if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA))
1127 : 0 : local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
1128 : :
1129 : : /* mac80211 supports multi BSSID, if the driver supports it */
1130 [ # # ]: 0 : if (ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID)) {
1131 : 0 : local->hw.wiphy->support_mbssid = true;
1132 [ # # ]: 0 : if (ieee80211_hw_check(&local->hw,
1133 : : SUPPORTS_ONLY_HE_MULTI_BSSID))
1134 : 0 : local->hw.wiphy->support_only_he_mbssid = true;
1135 : : else
1136 : 0 : local->ext_capa[2] |=
1137 : : WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
1138 : : }
1139 : :
1140 : 0 : local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
1141 : :
1142 : 0 : result = wiphy_register(local->hw.wiphy);
1143 [ # # ]: 0 : if (result < 0)
1144 : 0 : goto fail_wiphy_register;
1145 : :
1146 : : /*
1147 : : * We use the number of queues for feature tests (QoS, HT) internally
1148 : : * so restrict them appropriately.
1149 : : */
1150 [ # # ]: 0 : if (hw->queues > IEEE80211_MAX_QUEUES)
1151 : 0 : hw->queues = IEEE80211_MAX_QUEUES;
1152 : :
1153 : 0 : local->workqueue =
1154 [ # # ]: 0 : alloc_ordered_workqueue("%s", 0, wiphy_name(local->hw.wiphy));
1155 [ # # ]: 0 : if (!local->workqueue) {
1156 : 0 : result = -ENOMEM;
1157 : 0 : goto fail_workqueue;
1158 : : }
1159 : :
1160 : : /*
1161 : : * The hardware needs headroom for sending the frame,
1162 : : * and we need some headroom for passing the frame to monitor
1163 : : * interfaces, but never both at the same time.
1164 : : */
1165 : 0 : local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
1166 : : IEEE80211_TX_STATUS_HEADROOM);
1167 : :
1168 : 0 : debugfs_hw_add(local);
1169 : :
1170 : : /*
1171 : : * if the driver doesn't specify a max listen interval we
1172 : : * use 5 which should be a safe default
1173 : : */
1174 [ # # ]: 0 : if (local->hw.max_listen_interval == 0)
1175 : 0 : local->hw.max_listen_interval = 5;
1176 : :
1177 : 0 : local->hw.conf.listen_interval = local->hw.max_listen_interval;
1178 : :
1179 : 0 : local->dynamic_ps_forced_timeout = -1;
1180 : :
1181 [ # # ]: 0 : if (!local->hw.max_nan_de_entries)
1182 : 0 : local->hw.max_nan_de_entries = IEEE80211_MAX_NAN_INSTANCE_ID;
1183 : :
1184 [ # # ]: 0 : if (!local->hw.weight_multiplier)
1185 : 0 : local->hw.weight_multiplier = 1;
1186 : :
1187 : 0 : result = ieee80211_wep_init(local);
1188 [ # # ]: 0 : if (result < 0)
1189 : 0 : wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
1190 : : result);
1191 : :
1192 : 0 : local->hw.conf.flags = IEEE80211_CONF_IDLE;
1193 : :
1194 : 0 : ieee80211_led_init(local);
1195 : :
1196 : 0 : result = ieee80211_txq_setup_flows(local);
1197 [ # # ]: 0 : if (result)
1198 : 0 : goto fail_flows;
1199 : :
1200 : 0 : rtnl_lock();
1201 : :
1202 : 0 : result = ieee80211_init_rate_ctrl_alg(local,
1203 : : hw->rate_control_algorithm);
1204 [ # # ]: 0 : if (result < 0) {
1205 : 0 : wiphy_debug(local->hw.wiphy,
1206 : : "Failed to initialize rate control algorithm\n");
1207 : 0 : goto fail_rate;
1208 : : }
1209 : :
1210 [ # # ]: 0 : if (local->rate_ctrl) {
1211 : 0 : clear_bit(IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW, hw->flags);
1212 [ # # ]: 0 : if (local->rate_ctrl->ops->capa & RATE_CTRL_CAPA_VHT_EXT_NSS_BW)
1213 : 0 : ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
1214 : : }
1215 : :
1216 : : /*
1217 : : * If the VHT capabilities don't have IEEE80211_VHT_EXT_NSS_BW_CAPABLE,
1218 : : * or have it when we don't, copy the sband structure and set/clear it.
1219 : : * This is necessary because rate scaling algorithms could be switched
1220 : : * and have different support values.
1221 : : * Print a message so that in the common case the reallocation can be
1222 : : * avoided.
1223 : : */
1224 : : BUILD_BUG_ON(NUM_NL80211_BANDS > 8 * sizeof(local->sband_allocated));
1225 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++) {
1226 : 0 : struct ieee80211_supported_band *sband;
1227 : 0 : bool local_cap, ie_cap;
1228 : :
1229 : 0 : local_cap = ieee80211_hw_check(hw, SUPPORTS_VHT_EXT_NSS_BW);
1230 : :
1231 : 0 : sband = local->hw.wiphy->bands[band];
1232 [ # # # # ]: 0 : if (!sband || !sband->vht_cap.vht_supported)
1233 : 0 : continue;
1234 : :
1235 : 0 : ie_cap = !!(sband->vht_cap.vht_mcs.tx_highest &
1236 : : cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE));
1237 : :
1238 [ # # ]: 0 : if (local_cap == ie_cap)
1239 : 0 : continue;
1240 : :
1241 : 0 : sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL);
1242 [ # # ]: 0 : if (!sband) {
1243 : 0 : result = -ENOMEM;
1244 : 0 : goto fail_rate;
1245 : : }
1246 : :
1247 : 0 : wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",
1248 : : band);
1249 : :
1250 : 0 : sband->vht_cap.vht_mcs.tx_highest ^=
1251 : : cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
1252 : :
1253 : 0 : local->hw.wiphy->bands[band] = sband;
1254 : 0 : local->sband_allocated |= BIT(band);
1255 : : }
1256 : :
1257 : : /* add one default STA interface if supported */
1258 [ # # # # ]: 0 : if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
1259 : : !ieee80211_hw_check(hw, NO_AUTO_VIF)) {
1260 : 0 : struct vif_params params = {0};
1261 : :
1262 : 0 : result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL,
1263 : : NL80211_IFTYPE_STATION, ¶ms);
1264 [ # # ]: 0 : if (result)
1265 : 0 : wiphy_warn(local->hw.wiphy,
1266 : : "Failed to add default virtual iface\n");
1267 : : }
1268 : :
1269 : 0 : rtnl_unlock();
1270 : :
1271 : : #ifdef CONFIG_INET
1272 : 0 : local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
1273 : 0 : result = register_inetaddr_notifier(&local->ifa_notifier);
1274 [ # # ]: 0 : if (result)
1275 : 0 : goto fail_ifa;
1276 : : #endif
1277 : :
1278 : : #if IS_ENABLED(CONFIG_IPV6)
1279 : 0 : local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
1280 : 0 : result = register_inet6addr_notifier(&local->ifa6_notifier);
1281 [ # # ]: 0 : if (result)
1282 : 0 : goto fail_ifa6;
1283 : : #endif
1284 : :
1285 : : return 0;
1286 : :
1287 : : #if IS_ENABLED(CONFIG_IPV6)
1288 : : fail_ifa6:
1289 : : #ifdef CONFIG_INET
1290 : 0 : unregister_inetaddr_notifier(&local->ifa_notifier);
1291 : : #endif
1292 : : #endif
1293 : : #if defined(CONFIG_INET) || defined(CONFIG_IPV6)
1294 : 0 : fail_ifa:
1295 : : #endif
1296 : 0 : rtnl_lock();
1297 : 0 : rate_control_deinitialize(local);
1298 : 0 : ieee80211_remove_interfaces(local);
1299 : 0 : fail_rate:
1300 : 0 : rtnl_unlock();
1301 : 0 : fail_flows:
1302 : 0 : ieee80211_led_exit(local);
1303 : 0 : destroy_workqueue(local->workqueue);
1304 : 0 : fail_workqueue:
1305 : 0 : wiphy_unregister(local->hw.wiphy);
1306 : 0 : fail_wiphy_register:
1307 [ # # ]: 0 : if (local->wiphy_ciphers_allocated)
1308 : 0 : kfree(local->hw.wiphy->cipher_suites);
1309 : 0 : kfree(local->int_scan_req);
1310 : 0 : return result;
1311 : : }
1312 : : EXPORT_SYMBOL(ieee80211_register_hw);
1313 : :
1314 : 0 : void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1315 : : {
1316 : 0 : struct ieee80211_local *local = hw_to_local(hw);
1317 : :
1318 : 0 : tasklet_kill(&local->tx_pending_tasklet);
1319 : 0 : tasklet_kill(&local->tasklet);
1320 : :
1321 : : #ifdef CONFIG_INET
1322 : 0 : unregister_inetaddr_notifier(&local->ifa_notifier);
1323 : : #endif
1324 : : #if IS_ENABLED(CONFIG_IPV6)
1325 : 0 : unregister_inet6addr_notifier(&local->ifa6_notifier);
1326 : : #endif
1327 : :
1328 : 0 : rtnl_lock();
1329 : :
1330 : : /*
1331 : : * At this point, interface list manipulations are fine
1332 : : * because the driver cannot be handing us frames any
1333 : : * more and the tasklet is killed.
1334 : : */
1335 : 0 : ieee80211_remove_interfaces(local);
1336 : :
1337 : 0 : rtnl_unlock();
1338 : :
1339 : 0 : cancel_delayed_work_sync(&local->roc_work);
1340 : 0 : cancel_work_sync(&local->restart_work);
1341 : 0 : cancel_work_sync(&local->reconfig_filter);
1342 : 0 : cancel_work_sync(&local->tdls_chsw_work);
1343 : 0 : flush_work(&local->sched_scan_stopped_work);
1344 : 0 : flush_work(&local->radar_detected_work);
1345 : :
1346 : 0 : ieee80211_clear_tx_pending(local);
1347 : 0 : rate_control_deinitialize(local);
1348 : :
1349 [ # # # # ]: 0 : if (skb_queue_len(&local->skb_queue) ||
1350 [ # # ]: 0 : skb_queue_len(&local->skb_queue_unreliable))
1351 : 0 : wiphy_warn(local->hw.wiphy, "skb_queue not empty\n");
1352 : 0 : skb_queue_purge(&local->skb_queue);
1353 : 0 : skb_queue_purge(&local->skb_queue_unreliable);
1354 : 0 : skb_queue_purge(&local->skb_queue_tdls_chsw);
1355 : :
1356 : 0 : destroy_workqueue(local->workqueue);
1357 : 0 : wiphy_unregister(local->hw.wiphy);
1358 : 0 : ieee80211_led_exit(local);
1359 : 0 : kfree(local->int_scan_req);
1360 : 0 : }
1361 : : EXPORT_SYMBOL(ieee80211_unregister_hw);
1362 : :
1363 : 0 : static int ieee80211_free_ack_frame(int id, void *p, void *data)
1364 : : {
1365 [ # # ]: 0 : WARN_ONCE(1, "Have pending ack frames!\n");
1366 : 0 : kfree_skb(p);
1367 : 0 : return 0;
1368 : : }
1369 : :
1370 : 0 : void ieee80211_free_hw(struct ieee80211_hw *hw)
1371 : : {
1372 [ # # ]: 0 : struct ieee80211_local *local = hw_to_local(hw);
1373 : 0 : enum nl80211_band band;
1374 : :
1375 [ # # ]: 0 : mutex_destroy(&local->iflist_mtx);
1376 : 0 : mutex_destroy(&local->mtx);
1377 : :
1378 [ # # ]: 0 : if (local->wiphy_ciphers_allocated)
1379 : 0 : kfree(local->hw.wiphy->cipher_suites);
1380 : :
1381 : 0 : idr_for_each(&local->ack_status_frames,
1382 : : ieee80211_free_ack_frame, NULL);
1383 : 0 : idr_destroy(&local->ack_status_frames);
1384 : :
1385 : 0 : sta_info_stop(local);
1386 : :
1387 : 0 : ieee80211_free_led_names(local);
1388 : :
1389 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++) {
1390 [ # # ]: 0 : if (!(local->sband_allocated & BIT(band)))
1391 : 0 : continue;
1392 : 0 : kfree(local->hw.wiphy->bands[band]);
1393 : : }
1394 : :
1395 : 0 : wiphy_free(local->hw.wiphy);
1396 : 0 : }
1397 : : EXPORT_SYMBOL(ieee80211_free_hw);
1398 : :
1399 : 78 : static int __init ieee80211_init(void)
1400 : : {
1401 : 78 : struct sk_buff *skb;
1402 : 78 : int ret;
1403 : :
1404 : 78 : BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb));
1405 : 78 : BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
1406 : : IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
1407 : :
1408 : 78 : ret = rc80211_minstrel_init();
1409 [ + - ]: 78 : if (ret)
1410 : : return ret;
1411 : :
1412 : 78 : ret = ieee80211_iface_init();
1413 [ - + ]: 78 : if (ret)
1414 : 0 : goto err_netdev;
1415 : :
1416 : : return 0;
1417 : : err_netdev:
1418 : 0 : rc80211_minstrel_exit();
1419 : :
1420 : 0 : return ret;
1421 : : }
1422 : :
1423 : 0 : static void __exit ieee80211_exit(void)
1424 : : {
1425 : 0 : rc80211_minstrel_exit();
1426 : :
1427 : 0 : ieee80211s_stop();
1428 : :
1429 : 0 : ieee80211_iface_exit();
1430 : :
1431 : 0 : rcu_barrier();
1432 : 0 : }
1433 : :
1434 : :
1435 : : subsys_initcall(ieee80211_init);
1436 : : module_exit(ieee80211_exit);
1437 : :
1438 : : MODULE_DESCRIPTION("IEEE 802.11 subsystem");
1439 : : MODULE_LICENSE("GPL");
|