Blame view
net/mac80211/iface.c
55.9 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
f0706e828 [MAC80211]: Add m... |
2 |
/* |
c5d54fbf0 mac80211: remove ... |
3 |
* Interface handling |
0d143fe1e mac80211: move re... |
4 |
* |
f0706e828 [MAC80211]: Add m... |
5 6 7 |
* Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
75636525f mac80211: revamp ... |
8 |
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net> |
d98ad83ee mac80211: add Int... |
9 |
* Copyright 2013-2014 Intel Mobile Communications GmbH |
d2941df8f mac80211: recalcu... |
10 |
* Copyright (c) 2016 Intel Deutschland GmbH |
52b4810be mac80211: Remove ... |
11 |
* Copyright (C) 2018-2020 Intel Corporation |
f0706e828 [MAC80211]: Add m... |
12 |
*/ |
5a0e3ad6a include cleanup: ... |
13 |
#include <linux/slab.h> |
f0706e828 [MAC80211]: Add m... |
14 15 16 17 18 |
#include <linux/kernel.h> #include <linux/if_arp.h> #include <linux/netdevice.h> #include <linux/rtnetlink.h> #include <net/mac80211.h> |
cf0277e71 mac80211: fix skb... |
19 |
#include <net/ieee80211_radiotap.h> |
f0706e828 [MAC80211]: Add m... |
20 21 |
#include "ieee80211_i.h" #include "sta_info.h" |
e9f207f0f [MAC80211]: Add d... |
22 |
#include "debugfs_netdev.h" |
ee3858551 mac80211: mesh da... |
23 |
#include "mesh.h" |
0d143fe1e mac80211: move re... |
24 |
#include "led.h" |
244879813 mac80211: add dri... |
25 |
#include "driver-ops.h" |
cf0277e71 mac80211: fix skb... |
26 |
#include "wme.h" |
1be7fe8de mac80211: fix for... |
27 |
#include "rate.h" |
0d143fe1e mac80211: move re... |
28 |
|
c771c9d8d mac80211: add int... |
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/** * DOC: Interface list locking * * The interface list in each struct ieee80211_local is protected * three-fold: * * (1) modifications may only be done under the RTNL * (2) modifications and readers are protected against each other by * the iflist_mtx. * (3) modifications are done in an RCU manner so atomic readers * can traverse the list in RCU-safe blocks. * * As a consequence, reads (traversals) of the list can be protected * by either the RTNL, the iflist_mtx or RCU. */ |
42bd20d99 mac80211: add sup... |
44 |
static void ieee80211_iface_work(struct work_struct *work); |
1ea6f9c0d mac80211: handle ... |
45 46 47 48 49 50 51 52 53 54 55 |
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) { struct ieee80211_chanctx_conf *chanctx_conf; int power; rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!chanctx_conf) { rcu_read_unlock(); return false; } |
0430c8834 cfg80211/mac80211... |
56 |
power = ieee80211_chandef_max_power(&chanctx_conf->def); |
1ea6f9c0d mac80211: handle ... |
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
rcu_read_unlock(); if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) power = min(power, sdata->user_power_level); if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) power = min(power, sdata->ap_power_level); if (power != sdata->vif.bss_conf.txpower) { sdata->vif.bss_conf.txpower = power; ieee80211_hw_config(sdata->local, 0); return true; } return false; } |
db82d8a96 mac80211: enable ... |
73 74 |
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, bool update_bss) |
1ea6f9c0d mac80211: handle ... |
75 |
{ |
5ad11b50f mac80211: ensure ... |
76 77 |
if (__ieee80211_recalc_txpower(sdata) || (update_bss && ieee80211_sdata_running(sdata))) |
1ea6f9c0d mac80211: handle ... |
78 79 |
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); } |
c771c9d8d mac80211: add int... |
80 |
|
62a40a155 mac80211: fix LED... |
81 |
static u32 __ieee80211_idle_off(struct ieee80211_local *local) |
cc45ae547 mac80211: make __... |
82 83 84 85 86 87 88 |
{ if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) return 0; local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; return IEEE80211_CONF_CHANGE_IDLE; } |
62a40a155 mac80211: fix LED... |
89 |
static u32 __ieee80211_idle_on(struct ieee80211_local *local) |
cc45ae547 mac80211: make __... |
90 91 92 |
{ if (local->hw.conf.flags & IEEE80211_CONF_IDLE) return 0; |
3b24f4c65 mac80211: let flu... |
93 |
ieee80211_flush_queues(local, NULL, false); |
cc45ae547 mac80211: make __... |
94 95 96 97 |
local->hw.conf.flags |= IEEE80211_CONF_IDLE; return IEEE80211_CONF_CHANGE_IDLE; } |
62a40a155 mac80211: fix LED... |
98 99 |
static u32 __ieee80211_recalc_idle(struct ieee80211_local *local, bool force_active) |
cc45ae547 mac80211: make __... |
100 |
{ |
1d5e1266c mac80211: simplif... |
101 |
bool working, scanning, active; |
cc45ae547 mac80211: make __... |
102 |
unsigned int led_trig_start = 0, led_trig_stop = 0; |
cc45ae547 mac80211: make __... |
103 |
|
cc45ae547 mac80211: make __... |
104 |
lockdep_assert_held(&local->mtx); |
62a40a155 mac80211: fix LED... |
105 106 107 |
active = force_active || !list_empty(&local->chanctx_list) || local->monitors; |
cc45ae547 mac80211: make __... |
108 |
|
1d5e1266c mac80211: simplif... |
109 110 |
working = !local->ops->remain_on_channel && !list_empty(&local->roc_list); |
cc45ae547 mac80211: make __... |
111 |
|
f1e3e0515 mac80211: remove ... |
112 113 |
scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); |
cc45ae547 mac80211: make __... |
114 |
|
cc45ae547 mac80211: make __... |
115 116 117 118 |
if (working || scanning) led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; else led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
fd0f979a1 mac80211: simplif... |
119 |
if (active) |
cc45ae547 mac80211: make __... |
120 121 122 123 124 |
led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; else led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); |
fd0f979a1 mac80211: simplif... |
125 |
if (working || scanning || active) |
62a40a155 mac80211: fix LED... |
126 127 128 129 130 131 132 133 134 135 136 137 |
return __ieee80211_idle_off(local); return __ieee80211_idle_on(local); } u32 ieee80211_idle_off(struct ieee80211_local *local) { return __ieee80211_recalc_idle(local, true); } void ieee80211_recalc_idle(struct ieee80211_local *local) { u32 change = __ieee80211_recalc_idle(local, false); |
fd0f979a1 mac80211: simplif... |
138 139 |
if (change) ieee80211_hw_config(local, change); |
cc45ae547 mac80211: make __... |
140 |
} |
3899ba90a Merge branch 'mas... |
141 |
static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, |
31eba5bc5 mac80211: support... |
142 |
bool check_dup) |
478622e81 mac80211: reject ... |
143 |
{ |
ac20976dc mac80211: Allow s... |
144 145 |
struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *iter; |
478622e81 mac80211: reject ... |
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
u64 new, mask, tmp; u8 *m; int ret = 0; if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) return 0; m = addr; new = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); m = local->hw.wiphy->addr_mask; mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); |
31eba5bc5 mac80211: support... |
162 163 |
if (!check_dup) return ret; |
478622e81 mac80211: reject ... |
164 165 |
mutex_lock(&local->iflist_mtx); |
ac20976dc mac80211: Allow s... |
166 167 |
list_for_each_entry(iter, &local->interfaces, list) { if (iter == sdata) |
478622e81 mac80211: reject ... |
168 |
continue; |
3899ba90a Merge branch 'mas... |
169 |
if (iter->vif.type == NL80211_IFTYPE_MONITOR && |
d82121845 mac80211: refacto... |
170 |
!(iter->u.mntr.flags & MONITOR_FLAG_ACTIVE)) |
478622e81 mac80211: reject ... |
171 |
continue; |
ac20976dc mac80211: Allow s... |
172 |
m = iter->vif.addr; |
478622e81 mac80211: reject ... |
173 174 175 176 177 178 179 180 181 182 183 184 185 |
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); if ((new & ~mask) != (tmp & ~mask)) { ret = -EINVAL; break; } } mutex_unlock(&local->iflist_mtx); return ret; } |
47846c9b0 mac80211: reduce ... |
186 187 188 |
static int ieee80211_change_mac(struct net_device *dev, void *addr) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
fc5f75773 mac80211: fix iee... |
189 |
struct sockaddr *sa = addr; |
31eba5bc5 mac80211: support... |
190 |
bool check_dup = true; |
47846c9b0 mac80211: reduce ... |
191 |
int ret; |
9607e6b66 mac80211: add iee... |
192 |
if (ieee80211_sdata_running(sdata)) |
47846c9b0 mac80211: reduce ... |
193 |
return -EBUSY; |
31eba5bc5 mac80211: support... |
194 |
if (sdata->vif.type == NL80211_IFTYPE_MONITOR && |
d82121845 mac80211: refacto... |
195 |
!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) |
31eba5bc5 mac80211: support... |
196 |
check_dup = false; |
3899ba90a Merge branch 'mas... |
197 |
ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup); |
478622e81 mac80211: reject ... |
198 199 |
if (ret) return ret; |
fc5f75773 mac80211: fix iee... |
200 |
ret = eth_mac_addr(dev, sa); |
47846c9b0 mac80211: reduce ... |
201 202 |
if (ret == 0) |
fc5f75773 mac80211: fix iee... |
203 |
memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); |
47846c9b0 mac80211: reduce ... |
204 205 206 |
return ret; } |
0d143fe1e mac80211: move re... |
207 208 209 210 |
static inline int identical_mac_addr_allowed(int type1, int type2) { return type1 == NL80211_IFTYPE_MONITOR || type2 == NL80211_IFTYPE_MONITOR || |
f142c6b90 mac80211: support... |
211 212 |
type1 == NL80211_IFTYPE_P2P_DEVICE || type2 == NL80211_IFTYPE_P2P_DEVICE || |
0d143fe1e mac80211: move re... |
213 214 215 216 217 218 219 220 221 |
(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || (type1 == NL80211_IFTYPE_WDS && (type2 == NL80211_IFTYPE_WDS || type2 == NL80211_IFTYPE_AP)) || (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) || (type1 == NL80211_IFTYPE_AP_VLAN && (type2 == NL80211_IFTYPE_AP || type2 == NL80211_IFTYPE_AP_VLAN)); } |
87490f6db mac80211: split o... |
222 223 |
static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype iftype) |
0d143fe1e mac80211: move re... |
224 |
{ |
b4a4bf5d7 mac80211: fixups ... |
225 |
struct ieee80211_local *local = sdata->local; |
87490f6db mac80211: split o... |
226 |
struct ieee80211_sub_if_data *nsdata; |
b6a550156 cfg80211/mac80211... |
227 |
int ret; |
0d143fe1e mac80211: move re... |
228 |
|
87490f6db mac80211: split o... |
229 |
ASSERT_RTNL(); |
0d143fe1e mac80211: move re... |
230 231 232 |
/* we hold the RTNL here so can safely walk the list */ list_for_each_entry(nsdata, &local->interfaces, list) { |
371a255e8 mac80211: make ie... |
233 |
if (nsdata != sdata && ieee80211_sdata_running(nsdata)) { |
0d143fe1e mac80211: move re... |
234 |
/* |
239281f80 mac80211: 802.11p... |
235 236 237 238 239 240 241 242 243 |
* Only OCB and monitor mode may coexist */ if ((sdata->vif.type == NL80211_IFTYPE_OCB && nsdata->vif.type != NL80211_IFTYPE_MONITOR) || (sdata->vif.type != NL80211_IFTYPE_MONITOR && nsdata->vif.type == NL80211_IFTYPE_OCB)) return -EBUSY; /* |
0d143fe1e mac80211: move re... |
244 245 246 247 248 249 250 251 252 |
* Allow only a single IBSS interface to be up at any * time. This is restricted because beacon distribution * cannot work properly if both are in the same IBSS. * * To remove this restriction we'd have to disallow them * from setting the same SSID on different IBSS interfaces * belonging to the same hardware. Then, however, we're * faced with having to adopt two different TSF timers... */ |
87490f6db mac80211: split o... |
253 |
if (iftype == NL80211_IFTYPE_ADHOC && |
0d143fe1e mac80211: move re... |
254 255 |
nsdata->vif.type == NL80211_IFTYPE_ADHOC) return -EBUSY; |
73da7d5ba mac80211: add cha... |
256 257 258 259 260 261 |
/* * will not add another interface while any channel * switch is active. */ if (nsdata->vif.csa_active) return -EBUSY; |
0d143fe1e mac80211: move re... |
262 263 264 265 266 |
/* * The remaining checks are only performed for interfaces * with the same MAC address. */ |
371a255e8 mac80211: make ie... |
267 268 |
if (!ether_addr_equal(sdata->vif.addr, nsdata->vif.addr)) |
0d143fe1e mac80211: move re... |
269 270 271 272 273 |
continue; /* * check whether it may have the same address */ |
87490f6db mac80211: split o... |
274 |
if (!identical_mac_addr_allowed(iftype, |
0d143fe1e mac80211: move re... |
275 276 277 278 279 280 |
nsdata->vif.type)) return -ENOTUNIQ; /* * can only add VLANs to enabled APs */ |
87490f6db mac80211: split o... |
281 |
if (iftype == NL80211_IFTYPE_AP_VLAN && |
0d143fe1e mac80211: move re... |
282 283 284 285 |
nsdata->vif.type == NL80211_IFTYPE_AP) sdata->bss = &nsdata->u.ap; } } |
b6a550156 cfg80211/mac80211... |
286 287 288 289 |
mutex_lock(&local->chanctx_mtx); ret = ieee80211_check_combinations(sdata, NULL, 0, 0); mutex_unlock(&local->chanctx_mtx); return ret; |
87490f6db mac80211: split o... |
290 |
} |
a98655387 mac80211: fix cha... |
291 292 |
static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype iftype) |
3a25a8c8b mac80211: add imp... |
293 294 295 |
{ int n_queues = sdata->local->hw.queues; int i; |
708d50edb mac80211: add boi... |
296 297 |
if (iftype == NL80211_IFTYPE_NAN) return 0; |
a98655387 mac80211: fix cha... |
298 |
if (iftype != NL80211_IFTYPE_P2P_DEVICE) { |
0ef24e528 mac80211: Do not ... |
299 300 301 302 303 304 305 306 |
for (i = 0; i < IEEE80211_NUM_ACS; i++) { if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == IEEE80211_INVAL_HW_QUEUE)) return -EINVAL; if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >= n_queues)) return -EINVAL; } |
3a25a8c8b mac80211: add imp... |
307 |
} |
a98655387 mac80211: fix cha... |
308 309 310 |
if ((iftype != NL80211_IFTYPE_AP && iftype != NL80211_IFTYPE_P2P_GO && iftype != NL80211_IFTYPE_MESH_POINT) || |
30686bf7f mac80211: convert... |
311 |
!ieee80211_hw_check(&sdata->local->hw, QUEUE_CONTROL)) { |
3a25a8c8b mac80211: add imp... |
312 313 314 315 316 317 318 319 320 321 322 323 |
sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; return 0; } if (WARN_ON_ONCE(sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE)) return -EINVAL; if (WARN_ON_ONCE(sdata->vif.cab_queue >= n_queues)) return -EINVAL; return 0; } |
4b7afb52c mac80211: reorgan... |
324 |
static int ieee80211_open(struct net_device *dev) |
6aea26ce5 mac80211: rework ... |
325 |
{ |
4b7afb52c mac80211: reorgan... |
326 327 328 329 330 331 332 333 334 335 336 337 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int err; /* fail early if user set an invalid address */ if (!is_valid_ether_addr(dev->dev_addr)) return -EADDRNOTAVAIL; err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); if (err) return err; return ieee80211_do_open(&sdata->wdev, true); |
6aea26ce5 mac80211: rework ... |
338 |
} |
4b7afb52c mac80211: reorgan... |
339 340 |
static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down) |
6aea26ce5 mac80211: rework ... |
341 342 |
{ struct ieee80211_local *local = sdata->local; |
4b7afb52c mac80211: reorgan... |
343 344 345 346 347 348 349 350 |
unsigned long flags; struct sk_buff *skb, *tmp; u32 hw_reconf_flags = 0; int i, flushed; struct ps_data *ps; struct cfg80211_chan_def chandef; bool cancel_scan; struct cfg80211_nan_func *func; |
6aea26ce5 mac80211: rework ... |
351 |
|
4b7afb52c mac80211: reorgan... |
352 |
clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
6aea26ce5 mac80211: rework ... |
353 |
|
4b7afb52c mac80211: reorgan... |
354 355 356 |
cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; if (cancel_scan) ieee80211_scan_cancel(local); |
6aea26ce5 mac80211: rework ... |
357 |
|
4b7afb52c mac80211: reorgan... |
358 359 360 361 362 |
/* * Stop TX on this interface first. */ if (sdata->dev) netif_tx_stop_all_queues(sdata->dev); |
6aea26ce5 mac80211: rework ... |
363 |
|
4b7afb52c mac80211: reorgan... |
364 |
ieee80211_roc_purge(local, sdata); |
6aea26ce5 mac80211: rework ... |
365 |
|
4b7afb52c mac80211: reorgan... |
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: ieee80211_mgd_stop(sdata); break; case NL80211_IFTYPE_ADHOC: ieee80211_ibss_stop(sdata); break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) break; list_del_rcu(&sdata->u.mntr.list); break; default: break; } |
6aea26ce5 mac80211: rework ... |
381 |
|
4b7afb52c mac80211: reorgan... |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
/* * Remove all stations associated with this interface. * * This must be done before calling ops->remove_interface() * because otherwise we can later invoke ops->sta_notify() * whenever the STAs are removed, and that invalidates driver * assumptions about always getting a vif pointer that is valid * (because if we remove a STA after ops->remove_interface() * the driver will have removed the vif info already!) * * In WDS mode a station must exist here and be flushed, for * AP_VLANs stations may exist since there's nothing else that * would have removed them, but in other modes there shouldn't * be any stations. */ flushed = sta_info_flush(sdata); WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); |
6aea26ce5 mac80211: rework ... |
401 |
|
4b7afb52c mac80211: reorgan... |
402 403 404 |
/* don't count this interface for allmulti while it is down */ if (sdata->flags & IEEE80211_SDATA_ALLMULTI) atomic_dec(&local->iff_allmultis); |
6aea26ce5 mac80211: rework ... |
405 |
|
4b7afb52c mac80211: reorgan... |
406 407 408 409 410 |
if (sdata->vif.type == NL80211_IFTYPE_AP) { local->fif_pspoll--; local->fif_probe_req--; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { local->fif_probe_req--; |
6aea26ce5 mac80211: rework ... |
411 |
} |
4b7afb52c mac80211: reorgan... |
412 413 414 415 416 417 418 |
if (sdata->dev) { netif_addr_lock_bh(sdata->dev); spin_lock_bh(&local->filter_lock); __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, sdata->dev->addr_len); spin_unlock_bh(&local->filter_lock); netif_addr_unlock_bh(sdata->dev); |
6aea26ce5 mac80211: rework ... |
419 |
} |
6aea26ce5 mac80211: rework ... |
420 |
|
4b7afb52c mac80211: reorgan... |
421 422 |
del_timer_sync(&local->dynamic_ps_timer); cancel_work_sync(&local->dynamic_ps_enable_work); |
6aea26ce5 mac80211: rework ... |
423 |
|
4b7afb52c mac80211: reorgan... |
424 425 426 427 428 429 430 431 432 433 |
cancel_work_sync(&sdata->recalc_smps); sdata_lock(sdata); mutex_lock(&local->mtx); sdata->vif.csa_active = false; if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.mgd.csa_waiting_bcn = false; if (sdata->csa_block_tx) { ieee80211_wake_vif_queues(local, sdata, IEEE80211_QUEUE_STOP_REASON_CSA); sdata->csa_block_tx = false; |
6aea26ce5 mac80211: rework ... |
434 |
} |
4b7afb52c mac80211: reorgan... |
435 436 |
mutex_unlock(&local->mtx); sdata_unlock(sdata); |
6aea26ce5 mac80211: rework ... |
437 |
|
4b7afb52c mac80211: reorgan... |
438 |
cancel_work_sync(&sdata->csa_finalize_work); |
85416a4fa mac80211: fix rx ... |
439 |
|
4b7afb52c mac80211: reorgan... |
440 |
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
85416a4fa mac80211: fix rx ... |
441 |
|
4b7afb52c mac80211: reorgan... |
442 443 444 445 446 447 448 449 450 451 |
if (sdata->wdev.cac_started) { chandef = sdata->vif.bss_conf.chandef; WARN_ON(local->suspended); mutex_lock(&local->mtx); ieee80211_vif_release_channel(sdata); mutex_unlock(&local->mtx); cfg80211_cac_event(sdata->dev, &chandef, NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); } |
85416a4fa mac80211: fix rx ... |
452 |
|
4b7afb52c mac80211: reorgan... |
453 454 455 |
/* APs need special treatment */ if (sdata->vif.type == NL80211_IFTYPE_AP) { struct ieee80211_sub_if_data *vlan, *tmpsdata; |
85416a4fa mac80211: fix rx ... |
456 |
|
4b7afb52c mac80211: reorgan... |
457 458 459 460 461 462 463 464 |
/* down all dependent devices, that is VLANs */ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, u.vlan.list) dev_close(vlan->dev); WARN_ON(!list_empty(&sdata->u.ap.vlans)); } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { /* remove all packets in parent bc_buf pointing to this dev */ ps = &sdata->bss->ps; |
3a25a8c8b mac80211: add imp... |
465 |
|
4b7afb52c mac80211: reorgan... |
466 467 468 469 470 471 472 473 474 |
spin_lock_irqsave(&ps->bc_buf.lock, flags); skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { if (skb->dev == sdata->dev) { __skb_unlink(skb, &ps->bc_buf); local->total_ps_buffered--; ieee80211_free_txskb(&local->hw, skb); } } spin_unlock_irqrestore(&ps->bc_buf.lock, flags); |
3a25a8c8b mac80211: add imp... |
475 |
} |
3a25a8c8b mac80211: add imp... |
476 |
|
4b7afb52c mac80211: reorgan... |
477 478 |
if (going_down) local->open_count--; |
4b6f1dd6a mac80211: add exp... |
479 |
|
4b7afb52c mac80211: reorgan... |
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: mutex_lock(&local->mtx); list_del(&sdata->u.vlan.list); mutex_unlock(&local->mtx); RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); /* see comment in the default case below */ ieee80211_free_keys(sdata, true); /* no need to tell driver */ break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { local->cooked_mntrs--; break; } |
685fb72b6 mac80211: iterate... |
495 |
|
4b7afb52c mac80211: reorgan... |
496 497 498 499 500 |
local->monitors--; if (local->monitors == 0) { local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; } |
4b6f1dd6a mac80211: add exp... |
501 |
|
4b7afb52c mac80211: reorgan... |
502 503 504 505 506 |
ieee80211_adjust_monitor_flags(sdata, -1); break; case NL80211_IFTYPE_NAN: /* clean all the functions */ spin_lock_bh(&sdata->u.nan.func_lock); |
4b6f1dd6a mac80211: add exp... |
507 |
|
4b7afb52c mac80211: reorgan... |
508 509 510 511 512 |
idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) { idr_remove(&sdata->u.nan.function_inst_ids, i); cfg80211_free_nan_func(func); } idr_destroy(&sdata->u.nan.function_inst_ids); |
3a25a8c8b mac80211: add imp... |
513 |
|
4b7afb52c mac80211: reorgan... |
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
spin_unlock_bh(&sdata->u.nan.func_lock); break; case NL80211_IFTYPE_P2P_DEVICE: /* relies on synchronize_rcu() below */ RCU_INIT_POINTER(local->p2p_sdata, NULL); fallthrough; default: cancel_work_sync(&sdata->work); /* * When we get here, the interface is marked down. * Free the remaining keys, if there are any * (which can happen in AP mode if userspace sets * keys before the interface is operating, and maybe * also in WDS mode) * * Force the key freeing to always synchronize_net() * to wait for the RX path in case it is using this * interface enqueuing frames at this very time on * another CPU. */ ieee80211_free_keys(sdata, true); skb_queue_purge(&sdata->skb_queue); |
4b6f1dd6a mac80211: add exp... |
536 |
} |
4b7afb52c mac80211: reorgan... |
537 538 539 540 541 542 543 544 545 |
spin_lock_irqsave(&local->queue_stop_reason_lock, flags); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { skb_queue_walk_safe(&local->pending[i], skb, tmp) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (info->control.vif == &sdata->vif) { __skb_unlink(skb, &local->pending[i]); ieee80211_free_txskb(&local->hw, skb); } } |
3a25a8c8b mac80211: add imp... |
546 |
} |
4b7afb52c mac80211: reorgan... |
547 |
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
3a25a8c8b mac80211: add imp... |
548 |
|
4b7afb52c mac80211: reorgan... |
549 550 |
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ieee80211_txq_remove_vlan(local, sdata); |
fab57a6cc mac80211: fix vir... |
551 |
|
4b7afb52c mac80211: reorgan... |
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
sdata->bss = NULL; if (local->open_count == 0) ieee80211_clear_tx_pending(local); sdata->vif.bss_conf.beacon_int = 0; /* * If the interface goes down while suspended, presumably because * the device was unplugged and that happens before our resume, * then the driver is already unconfigured and the remainder of * this function isn't needed. * XXX: what about WoWLAN? If the device has software state, e.g. * memory allocated, it might expect teardown commands from * mac80211 here? */ if (local->suspended) { WARN_ON(local->wowlan); WARN_ON(rtnl_dereference(local->monitor_sdata)); return; |
55de908ab mac80211: use cha... |
572 |
} |
4b7afb52c mac80211: reorgan... |
573 574 575 576 577 578 |
switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: break; case NL80211_IFTYPE_MONITOR: if (local->monitors == 0) ieee80211_del_virtual_monitor(local); |
42bd20d99 mac80211: add sup... |
579 |
|
4b7afb52c mac80211: reorgan... |
580 581 582 |
mutex_lock(&local->mtx); ieee80211_recalc_idle(local); mutex_unlock(&local->mtx); |
4b6f1dd6a mac80211: add exp... |
583 |
|
4b7afb52c mac80211: reorgan... |
584 585 |
if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) break; |
4b6f1dd6a mac80211: add exp... |
586 |
|
4b7afb52c mac80211: reorgan... |
587 588 589 590 591 |
fallthrough; default: if (going_down) drv_remove_interface(local, sdata); } |
4b6f1dd6a mac80211: add exp... |
592 |
|
4b7afb52c mac80211: reorgan... |
593 |
ieee80211_recalc_ps(local); |
8b305780e mac80211: fix vir... |
594 |
|
4b7afb52c mac80211: reorgan... |
595 596 |
if (cancel_scan) flush_delayed_work(&local->scan_work); |
4b6f1dd6a mac80211: add exp... |
597 |
|
4b7afb52c mac80211: reorgan... |
598 599 600 601 |
if (local->open_count == 0) { ieee80211_stop_device(local); /* no reconfiguring after stop! */ |
8b305780e mac80211: fix vir... |
602 603 |
return; } |
4b6f1dd6a mac80211: add exp... |
604 |
|
4b7afb52c mac80211: reorgan... |
605 606 607 |
/* do after stop to avoid reconfiguring when we stop anyway */ ieee80211_configure_filter(local); ieee80211_hw_config(local, hw_reconf_flags); |
8b305780e mac80211: fix vir... |
608 |
|
4b7afb52c mac80211: reorgan... |
609 610 611 |
if (local->monitors == local->open_count) ieee80211_add_virtual_monitor(local); } |
4b6f1dd6a mac80211: add exp... |
612 |
|
4b7afb52c mac80211: reorgan... |
613 614 615 |
static int ieee80211_stop(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
55de908ab mac80211: use cha... |
616 |
|
4b7afb52c mac80211: reorgan... |
617 |
ieee80211_do_stop(sdata, true); |
4b6f1dd6a mac80211: add exp... |
618 |
|
4b7afb52c mac80211: reorgan... |
619 |
return 0; |
4b6f1dd6a mac80211: add exp... |
620 |
} |
4b7afb52c mac80211: reorgan... |
621 |
static void ieee80211_set_multicast_list(struct net_device *dev) |
87490f6db mac80211: split o... |
622 |
{ |
4b7afb52c mac80211: reorgan... |
623 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
87490f6db mac80211: split o... |
624 |
struct ieee80211_local *local = sdata->local; |
4b7afb52c mac80211: reorgan... |
625 |
int allmulti, sdata_allmulti; |
87490f6db mac80211: split o... |
626 |
|
4b7afb52c mac80211: reorgan... |
627 628 |
allmulti = !!(dev->flags & IFF_ALLMULTI); sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); |
665c93a93 mac80211: add sup... |
629 |
|
4b7afb52c mac80211: reorgan... |
630 631 632 633 634 635 636 |
if (allmulti != sdata_allmulti) { if (dev->flags & IFF_ALLMULTI) atomic_inc(&local->iff_allmultis); else atomic_dec(&local->iff_allmultis); sdata->flags ^= IEEE80211_SDATA_ALLMULTI; } |
665c93a93 mac80211: add sup... |
637 |
|
4b7afb52c mac80211: reorgan... |
638 639 640 641 642 |
spin_lock_bh(&local->filter_lock); __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); spin_unlock_bh(&local->filter_lock); ieee80211_queue_work(&local->hw, &local->reconfig_filter); } |
665c93a93 mac80211: add sup... |
643 |
|
4b7afb52c mac80211: reorgan... |
644 645 646 647 648 649 650 |
/* * Called when the netdev is removed or, by the code below, before * the interface type changes. */ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) { int i; |
f9dca80b9 mac80211: fix AP_... |
651 |
|
4b7afb52c mac80211: reorgan... |
652 653 |
/* free extra data */ ieee80211_free_keys(sdata, false); |
f9dca80b9 mac80211: fix AP_... |
654 |
|
4b7afb52c mac80211: reorgan... |
655 |
ieee80211_debugfs_remove_netdev(sdata); |
0d143fe1e mac80211: move re... |
656 |
|
4b7afb52c mac80211: reorgan... |
657 658 659 |
for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) __skb_queue_purge(&sdata->fragments[i].skb_list); sdata->fragment_next = 0; |
0d143fe1e mac80211: move re... |
660 |
|
4b7afb52c mac80211: reorgan... |
661 662 663 |
if (ieee80211_vif_is_mesh(&sdata->vif)) ieee80211_mesh_teardown_sdata(sdata); } |
0d143fe1e mac80211: move re... |
664 |
|
4b7afb52c mac80211: reorgan... |
665 666 667 668 |
static void ieee80211_uninit(struct net_device *dev) { ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); } |
075e08477 Revert "mac80211:... |
669 |
|
4b7afb52c mac80211: reorgan... |
670 671 672 673 674 675 |
static u16 ieee80211_netdev_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev) { return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); } |
0d143fe1e mac80211: move re... |
676 |
|
4b7afb52c mac80211: reorgan... |
677 678 679 |
static void ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { |
6401297e7 mac80211: use new... |
680 |
dev_fetch_sw_netstats(stats, dev->tstats); |
4b7afb52c mac80211: reorgan... |
681 |
} |
e3b90ca28 mac80211: FIF_PSP... |
682 |
|
4b7afb52c mac80211: reorgan... |
683 684 685 686 687 688 689 690 691 692 |
static const struct net_device_ops ieee80211_dataif_ops = { .ndo_open = ieee80211_open, .ndo_stop = ieee80211_stop, .ndo_uninit = ieee80211_uninit, .ndo_start_xmit = ieee80211_subif_start_xmit, .ndo_set_rx_mode = ieee80211_set_multicast_list, .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_netdev_select_queue, .ndo_get_stats64 = ieee80211_get_stats64, }; |
e3b90ca28 mac80211: FIF_PSP... |
693 |
|
4b7afb52c mac80211: reorgan... |
694 695 696 697 698 699 700 701 702 |
static u16 ieee80211_monitor_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr; int len_rthdr; |
90e8f58df mac80211: fix drv... |
703 |
|
4b7afb52c mac80211: reorgan... |
704 705 |
if (local->hw.queues < IEEE80211_NUM_ACS) return 0; |
0d143fe1e mac80211: move re... |
706 |
|
4b7afb52c mac80211: reorgan... |
707 708 |
/* reset flags and info before parsing radiotap header */ memset(info, 0, sizeof(*info)); |
590345910 mac80211: call se... |
709 |
|
4b7afb52c mac80211: reorgan... |
710 711 |
if (!ieee80211_parse_tx_radiotap(skb, dev)) return 0; /* doesn't matter, frame will be dropped */ |
0d143fe1e mac80211: move re... |
712 |
|
4b7afb52c mac80211: reorgan... |
713 714 715 716 717 |
len_rthdr = ieee80211_get_radiotap_len(skb->data); hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); if (skb->len < len_rthdr + 2 || skb->len < len_rthdr + ieee80211_hdrlen(hdr->frame_control)) return 0; /* doesn't matter, frame will be dropped */ |
2d2080c3c mac80211: set run... |
718 |
|
4b7afb52c mac80211: reorgan... |
719 720 |
return ieee80211_select_queue_80211(sdata, skb, hdr); } |
0d143fe1e mac80211: move re... |
721 |
|
4b7afb52c mac80211: reorgan... |
722 723 724 725 726 727 728 729 730 731 |
static const struct net_device_ops ieee80211_monitorif_ops = { .ndo_open = ieee80211_open, .ndo_stop = ieee80211_stop, .ndo_uninit = ieee80211_uninit, .ndo_start_xmit = ieee80211_monitor_start_xmit, .ndo_set_rx_mode = ieee80211_set_multicast_list, .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_monitor_select_queue, .ndo_get_stats64 = ieee80211_get_stats64, }; |
0d143fe1e mac80211: move re... |
732 |
|
4b7afb52c mac80211: reorgan... |
733 734 735 736 737 738 739 740 741 742 |
static const struct net_device_ops ieee80211_dataif_8023_ops = { .ndo_open = ieee80211_open, .ndo_stop = ieee80211_stop, .ndo_uninit = ieee80211_uninit, .ndo_start_xmit = ieee80211_subif_start_xmit_8023, .ndo_set_rx_mode = ieee80211_set_multicast_list, .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_netdev_select_queue, .ndo_get_stats64 = ieee80211_get_stats64, }; |
1be7fe8de mac80211: fix for... |
743 |
|
4b7afb52c mac80211: reorgan... |
744 745 746 747 748 749 750 |
static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) { switch (iftype) { /* P2P GO and client are mapped to AP/STATION types */ case NL80211_IFTYPE_AP: case NL80211_IFTYPE_STATION: return true; |
f64331d58 mac80211: keep a ... |
751 |
default: |
4b7afb52c mac80211: reorgan... |
752 |
return false; |
0d143fe1e mac80211: move re... |
753 |
} |
4b7afb52c mac80211: reorgan... |
754 |
} |
0d143fe1e mac80211: move re... |
755 |
|
4b7afb52c mac80211: reorgan... |
756 757 758 759 |
static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; u32 flags; |
965bedadc mac80211: improve... |
760 |
|
4b7afb52c mac80211: reorgan... |
761 |
flags = sdata->vif.offload_flags; |
2b730daac mac80211: don't s... |
762 |
|
4b7afb52c mac80211: reorgan... |
763 764 765 |
if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && ieee80211_iftype_supports_encap_offload(sdata->vif.type)) { flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED; |
2b730daac mac80211: don't s... |
766 |
|
4b7afb52c mac80211: reorgan... |
767 768 769 |
if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && local->hw.wiphy->frag_threshold != (u32)-1) flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; |
2b730daac mac80211: don't s... |
770 |
|
4b7afb52c mac80211: reorgan... |
771 772 773 774 |
if (local->monitors) flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; } else { flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; |
2b730daac mac80211: don't s... |
775 |
} |
0d143fe1e mac80211: move re... |
776 |
|
4b7afb52c mac80211: reorgan... |
777 778 779 780 781 |
if (sdata->vif.offload_flags == flags) return false; sdata->vif.offload_flags = flags; return true; |
0d143fe1e mac80211: move re... |
782 |
} |
4b7afb52c mac80211: reorgan... |
783 |
static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) |
0d143fe1e mac80211: move re... |
784 |
{ |
4b7afb52c mac80211: reorgan... |
785 786 787 |
struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *bss = sdata; bool enabled; |
34d4bc4d4 mac80211: support... |
788 |
|
4b7afb52c mac80211: reorgan... |
789 790 791 |
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { if (!sdata->bss) return; |
34d4bc4d4 mac80211: support... |
792 |
|
4b7afb52c mac80211: reorgan... |
793 794 |
bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); } |
34d4bc4d4 mac80211: support... |
795 |
|
4b7afb52c mac80211: reorgan... |
796 797 798 |
if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || !ieee80211_iftype_supports_encap_offload(bss->vif.type)) return; |
34d4bc4d4 mac80211: support... |
799 |
|
4b7afb52c mac80211: reorgan... |
800 801 802 803 |
enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; if (sdata->wdev.use_4addr && !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) enabled = false; |
0d143fe1e mac80211: move re... |
804 |
|
4b7afb52c mac80211: reorgan... |
805 806 807 |
sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : &ieee80211_dataif_ops; } |
c29acf201 mac80211: abort s... |
808 |
|
4b7afb52c mac80211: reorgan... |
809 810 811 812 |
static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *vsdata; |
352ffad64 mac80211: unset S... |
813 |
|
4b7afb52c mac80211: reorgan... |
814 815 816 817 |
if (ieee80211_set_sdata_offload_flags(sdata)) { drv_update_vif_offload(local, sdata); ieee80211_set_vif_encap_ops(sdata); } |
0d143fe1e mac80211: move re... |
818 |
|
4b7afb52c mac80211: reorgan... |
819 820 821 822 |
list_for_each_entry(vsdata, &local->interfaces, list) { if (vsdata->vif.type != NL80211_IFTYPE_AP_VLAN || vsdata->bss != &sdata->u.ap) continue; |
af6b63741 mac80211: general... |
823 |
|
4b7afb52c mac80211: reorgan... |
824 |
ieee80211_set_vif_encap_ops(vsdata); |
8ffcc704c mac80211: avoid d... |
825 |
} |
4b7afb52c mac80211: reorgan... |
826 |
} |
cd7760e62 mac80211: add sup... |
827 |
|
4b7afb52c mac80211: reorgan... |
828 829 830 |
void ieee80211_recalc_offload(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; |
0d143fe1e mac80211: move re... |
831 |
|
4b7afb52c mac80211: reorgan... |
832 833 |
if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD)) return; |
0d143fe1e mac80211: move re... |
834 |
|
4b7afb52c mac80211: reorgan... |
835 |
mutex_lock(&local->iflist_mtx); |
e3b90ca28 mac80211: FIF_PSP... |
836 |
|
4b7afb52c mac80211: reorgan... |
837 838 839 840 841 |
list_for_each_entry(sdata, &local->interfaces, list) { if (!ieee80211_sdata_running(sdata)) continue; ieee80211_recalc_sdata_offload(sdata); |
f142c6b90 mac80211: support... |
842 |
} |
3ac64beec mac80211: allow c... |
843 |
|
4b7afb52c mac80211: reorgan... |
844 845 |
mutex_unlock(&local->iflist_mtx); } |
0d143fe1e mac80211: move re... |
846 |
|
4b7afb52c mac80211: reorgan... |
847 848 849 850 851 |
void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, const int offset) { struct ieee80211_local *local = sdata->local; u32 flags = sdata->u.mntr.flags; |
59af6928d mac80211: fix CSA... |
852 |
|
4b7afb52c mac80211: reorgan... |
853 854 855 856 |
#define ADJUST(_f, _s) do { \ if (flags & MONITOR_FLAG_##_f) \ local->fif_##_s += offset; \ } while (0) |
04ecd2578 mac80211: track n... |
857 |
|
4b7afb52c mac80211: reorgan... |
858 859 860 861 862 |
ADJUST(FCSFAIL, fcsfail); ADJUST(PLCPFAIL, plcpfail); ADJUST(CONTROL, control); ADJUST(CONTROL, pspoll); ADJUST(OTHER_BSS, other_bss); |
164eb02d0 mac80211: add rad... |
863 |
|
4b7afb52c mac80211: reorgan... |
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 |
#undef ADJUST } static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; int i; for (i = 0; i < IEEE80211_NUM_ACS; i++) { if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE; else if (local->hw.queues >= IEEE80211_NUM_ACS) sdata->vif.hw_queue[i] = i; else sdata->vif.hw_queue[i] = 0; |
164eb02d0 mac80211: add rad... |
879 |
} |
4b7afb52c mac80211: reorgan... |
880 881 |
sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; } |
164eb02d0 mac80211: add rad... |
882 |
|
4b7afb52c mac80211: reorgan... |
883 884 885 886 |
int ieee80211_add_virtual_monitor(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; int ret; |
0d143fe1e mac80211: move re... |
887 |
|
4b7afb52c mac80211: reorgan... |
888 889 |
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) return 0; |
397a7a24e mac80211: free ps... |
890 |
|
4b7afb52c mac80211: reorgan... |
891 |
ASSERT_RTNL(); |
0d143fe1e mac80211: move re... |
892 |
|
4b7afb52c mac80211: reorgan... |
893 894 |
if (local->monitor_sdata) return 0; |
0d143fe1e mac80211: move re... |
895 |
|
4b7afb52c mac80211: reorgan... |
896 897 898 |
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); if (!sdata) return -ENOMEM; |
0d143fe1e mac80211: move re... |
899 |
|
4b7afb52c mac80211: reorgan... |
900 901 902 903 904 905 |
/* set up data */ sdata->local = local; sdata->vif.type = NL80211_IFTYPE_MONITOR; snprintf(sdata->name, IFNAMSIZ, "%s-monitor", wiphy_name(local->hw.wiphy)); sdata->wdev.iftype = NL80211_IFTYPE_MONITOR; |
0d143fe1e mac80211: move re... |
906 |
|
4b7afb52c mac80211: reorgan... |
907 |
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; |
167e33f4f mac80211: Impleme... |
908 |
|
4b7afb52c mac80211: reorgan... |
909 |
ieee80211_set_default_queues(sdata); |
167e33f4f mac80211: Impleme... |
910 |
|
4b7afb52c mac80211: reorgan... |
911 912 913 914 915 916 |
ret = drv_add_interface(local, sdata); if (WARN_ON(ret)) { /* ok .. stupid driver, it asked for this! */ kfree(sdata); return ret; } |
bdeca45a0 mac80211: set SDA... |
917 |
set_bit(SDATA_STATE_RUNNING, &sdata->state); |
4b7afb52c mac80211: reorgan... |
918 919 920 921 |
ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR); if (ret) { kfree(sdata); return ret; |
0d143fe1e mac80211: move re... |
922 |
} |
4b7afb52c mac80211: reorgan... |
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
mutex_lock(&local->iflist_mtx); rcu_assign_pointer(local->monitor_sdata, sdata); mutex_unlock(&local->iflist_mtx); mutex_lock(&local->mtx); ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, IEEE80211_CHANCTX_EXCLUSIVE); mutex_unlock(&local->mtx); if (ret) { mutex_lock(&local->iflist_mtx); RCU_INIT_POINTER(local->monitor_sdata, NULL); mutex_unlock(&local->iflist_mtx); synchronize_net(); drv_remove_interface(local, sdata); kfree(sdata); return ret; |
5061b0c2b mac80211: coopera... |
939 |
} |
075e08477 Revert "mac80211:... |
940 |
|
4b7afb52c mac80211: reorgan... |
941 942 |
skb_queue_head_init(&sdata->skb_queue); INIT_WORK(&sdata->work, ieee80211_iface_work); |
531682159 mac80211: fix VLA... |
943 |
|
4b7afb52c mac80211: reorgan... |
944 945 |
return 0; } |
ba8c3d6f1 mac80211: add an ... |
946 |
|
4b7afb52c mac80211: reorgan... |
947 948 949 |
void ieee80211_del_virtual_monitor(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; |
b2c0958b2 mac80211: fix do_... |
950 |
|
4b7afb52c mac80211: reorgan... |
951 952 |
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) return; |
5c21e8100 mac80211: Clear b... |
953 |
|
4b7afb52c mac80211: reorgan... |
954 955 956 957 958 959 960 961 |
ASSERT_RTNL(); mutex_lock(&local->iflist_mtx); sdata = rcu_dereference_protected(local->monitor_sdata, lockdep_is_held(&local->iflist_mtx)); if (!sdata) { mutex_unlock(&local->iflist_mtx); |
b2c0958b2 mac80211: fix do_... |
962 963 |
return; } |
4b7afb52c mac80211: reorgan... |
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 |
RCU_INIT_POINTER(local->monitor_sdata, NULL); mutex_unlock(&local->iflist_mtx); synchronize_net(); mutex_lock(&local->mtx); ieee80211_vif_release_channel(sdata); mutex_unlock(&local->mtx); drv_remove_interface(local, sdata); kfree(sdata); } /* * NOTE: Be very careful when changing this function, it must NOT return * an error on interface type changes that have been pre-checked, so most * checks should be in ieee80211_check_concurrent_iface. */ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) { struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); struct net_device *dev = wdev->netdev; struct ieee80211_local *local = sdata->local; struct sta_info *sta; u32 changed = 0; int res; u32 hw_reconf_flags = 0; |
b2c0958b2 mac80211: fix do_... |
992 |
switch (sdata->vif.type) { |
4b7afb52c mac80211: reorgan... |
993 994 995 |
case NL80211_IFTYPE_WDS: if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) return -ENOLINK; |
b2c0958b2 mac80211: fix do_... |
996 |
break; |
4b7afb52c mac80211: reorgan... |
997 998 999 1000 1001 |
case NL80211_IFTYPE_AP_VLAN: { struct ieee80211_sub_if_data *master; if (!sdata->bss) return -ENOLINK; |
b2c0958b2 mac80211: fix do_... |
1002 1003 |
mutex_lock(&local->mtx); |
4b7afb52c mac80211: reorgan... |
1004 |
list_add(&sdata->u.vlan.list, &sdata->bss->vlans); |
b2c0958b2 mac80211: fix do_... |
1005 |
mutex_unlock(&local->mtx); |
31eba5bc5 mac80211: support... |
1006 |
|
4b7afb52c mac80211: reorgan... |
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 |
master = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); sdata->control_port_protocol = master->control_port_protocol; sdata->control_port_no_encrypt = master->control_port_no_encrypt; sdata->control_port_over_nl80211 = master->control_port_over_nl80211; sdata->control_port_no_preauth = master->control_port_no_preauth; sdata->vif.cab_queue = master->vif.cab_queue; memcpy(sdata->vif.hw_queue, master->vif.hw_queue, sizeof(sdata->vif.hw_queue)); sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef; |
b2c0958b2 mac80211: fix do_... |
1021 |
|
4b7afb52c mac80211: reorgan... |
1022 1023 1024 1025 |
mutex_lock(&local->key_mtx); sdata->crypto_tx_tailroom_needed_cnt += master->crypto_tx_tailroom_needed_cnt; mutex_unlock(&local->key_mtx); |
b2c0958b2 mac80211: fix do_... |
1026 |
|
4b7afb52c mac80211: reorgan... |
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 |
break; } case NL80211_IFTYPE_AP: sdata->bss = &sdata->u.ap; break; case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_NAN: /* no special treatment */ break; case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: /* cannot happen */ WARN_ON(1); break; } |
46238845b mac80211: properl... |
1049 |
|
b2c0958b2 mac80211: fix do_... |
1050 |
if (local->open_count == 0) { |
4b7afb52c mac80211: reorgan... |
1051 1052 1053 1054 1055 1056 1057 1058 |
res = drv_start(local); if (res) goto err_del_bss; /* we're brought up, everything changes */ hw_reconf_flags = ~0; ieee80211_led_radio(local, true); ieee80211_mod_tpt_led_trig(local, IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); |
b2c0958b2 mac80211: fix do_... |
1059 |
} |
4b7afb52c mac80211: reorgan... |
1060 1061 1062 1063 1064 1065 1066 1067 1068 |
/* * Copy the hopefully now-present MAC address to * this interface, if it has the special null one. */ if (dev && is_zero_ether_addr(dev->dev_addr)) { memcpy(dev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); |
34d4bc4d4 mac80211: support... |
1069 |
|
4b7afb52c mac80211: reorgan... |
1070 1071 1072 1073 1074 |
if (!is_valid_ether_addr(dev->dev_addr)) { res = -EADDRNOTAVAIL; goto err_stop; } } |
34d4bc4d4 mac80211: support... |
1075 |
|
4b7afb52c mac80211: reorgan... |
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 |
switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: /* no need to tell driver, but set carrier and chanctx */ if (rtnl_dereference(sdata->bss->beacon)) { ieee80211_vif_vlan_copy_chanctx(sdata); netif_carrier_on(dev); ieee80211_set_vif_encap_ops(sdata); } else { netif_carrier_off(dev); } break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { local->cooked_mntrs++; break; } |
5061b0c2b mac80211: coopera... |
1092 |
|
4b7afb52c mac80211: reorgan... |
1093 1094 1095 1096 1097 1098 1099 1100 1101 |
if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) { res = drv_add_interface(local, sdata); if (res) goto err_stop; } else if (local->monitors == 0 && local->open_count == 0) { res = ieee80211_add_virtual_monitor(local); if (res) goto err_stop; } |
0d143fe1e mac80211: move re... |
1102 |
|
4b7afb52c mac80211: reorgan... |
1103 1104 1105 1106 1107 1108 |
/* must be before the call to ieee80211_configure_filter */ local->monitors++; if (local->monitors == 1) { local->hw.conf.flags |= IEEE80211_CONF_MONITOR; hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; } |
0d143fe1e mac80211: move re... |
1109 |
|
4b7afb52c mac80211: reorgan... |
1110 1111 1112 1113 1114 1115 |
ieee80211_adjust_monitor_flags(sdata, 1); ieee80211_configure_filter(local); ieee80211_recalc_offload(local); mutex_lock(&local->mtx); ieee80211_recalc_idle(local); mutex_unlock(&local->mtx); |
0d143fe1e mac80211: move re... |
1116 |
|
4b7afb52c mac80211: reorgan... |
1117 1118 1119 1120 1121 1122 |
netif_carrier_on(dev); break; default: if (coming_up) { ieee80211_del_virtual_monitor(local); ieee80211_set_sdata_offload_flags(sdata); |
0d143fe1e mac80211: move re... |
1123 |
|
4b7afb52c mac80211: reorgan... |
1124 1125 1126 |
res = drv_add_interface(local, sdata); if (res) goto err_stop; |
0d143fe1e mac80211: move re... |
1127 |
|
4b7afb52c mac80211: reorgan... |
1128 1129 1130 1131 1132 1133 |
ieee80211_set_vif_encap_ops(sdata); res = ieee80211_check_queues(sdata, ieee80211_vif_type_p2p(&sdata->vif)); if (res) goto err_del_interface; } |
f0706e828 [MAC80211]: Add m... |
1134 |
|
4b7afb52c mac80211: reorgan... |
1135 1136 1137 |
if (sdata->vif.type == NL80211_IFTYPE_AP) { local->fif_pspoll++; local->fif_probe_req++; |
75636525f mac80211: revamp ... |
1138 |
|
4b7afb52c mac80211: reorgan... |
1139 1140 1141 1142 |
ieee80211_configure_filter(local); } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { local->fif_probe_req++; } |
aee14ceb5 mac80211: Reorder... |
1143 |
|
4b7afb52c mac80211: reorgan... |
1144 1145 1146 1147 |
if (sdata->vif.probe_req_reg) drv_config_iface_filter(local, sdata, FIF_PROBE_REQ, FIF_PROBE_REQ); |
11a843b7e [MAC80211]: rewor... |
1148 |
|
4b7afb52c mac80211: reorgan... |
1149 1150 1151 1152 |
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && sdata->vif.type != NL80211_IFTYPE_NAN) changed |= ieee80211_reset_erp_info(sdata); ieee80211_bss_info_change_notify(sdata, changed); |
f0706e828 [MAC80211]: Add m... |
1153 |
|
4b7afb52c mac80211: reorgan... |
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_OCB: netif_carrier_off(dev); break; case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_NAN: break; default: /* not reached */ WARN_ON(1); } |
f142c6b90 mac80211: support... |
1170 |
|
4b7afb52c mac80211: reorgan... |
1171 1172 1173 1174 1175 1176 1177 1178 1179 |
/* * Set default queue parameters so drivers don't * need to initialise the hardware if the hardware * doesn't start up with sane defaults. * Enable QoS for anything but station interfaces. */ ieee80211_set_wmm_default(sdata, true, sdata->vif.type != NL80211_IFTYPE_STATION); } |
cf0277e71 mac80211: fix skb... |
1180 |
|
4b7afb52c mac80211: reorgan... |
1181 |
set_bit(SDATA_STATE_RUNNING, &sdata->state); |
5a490510b mac80211: use per... |
1182 |
|
4b7afb52c mac80211: reorgan... |
1183 1184 1185 1186 1187 1188 1189 1190 1191 |
switch (sdata->vif.type) { case NL80211_IFTYPE_WDS: /* Create STA entry for the WDS peer */ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, GFP_KERNEL); if (!sta) { res = -ENOMEM; goto err_del_interface; } |
5a490510b mac80211: use per... |
1192 |
|
4b7afb52c mac80211: reorgan... |
1193 1194 1195 |
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
5a490510b mac80211: use per... |
1196 |
|
4b7afb52c mac80211: reorgan... |
1197 1198 1199 1200 1201 |
res = sta_info_insert(sta); if (res) { /* STA has been freed */ goto err_del_interface; } |
5a490510b mac80211: use per... |
1202 |
|
4b7afb52c mac80211: reorgan... |
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 |
rate_control_rate_init(sta); netif_carrier_on(dev); break; case NL80211_IFTYPE_P2P_DEVICE: rcu_assign_pointer(local->p2p_sdata, sdata); break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) break; list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list); break; default: break; |
5a490510b mac80211: use per... |
1216 |
} |
5a490510b mac80211: use per... |
1217 |
|
4b7afb52c mac80211: reorgan... |
1218 1219 1220 1221 1222 1223 1224 |
/* * set_multicast_list will be invoked by the networking core * which will check whether any increments here were done in * error and sync them down to the hardware as filter flags. */ if (sdata->flags & IEEE80211_SDATA_ALLMULTI) atomic_inc(&local->iff_allmultis); |
587e729ec mac80211: convert... |
1225 |
|
4b7afb52c mac80211: reorgan... |
1226 1227 |
if (coming_up) local->open_count++; |
cf0277e71 mac80211: fix skb... |
1228 |
|
4b7afb52c mac80211: reorgan... |
1229 1230 |
if (hw_reconf_flags) ieee80211_hw_config(local, hw_reconf_flags); |
cf0277e71 mac80211: fix skb... |
1231 |
|
4b7afb52c mac80211: reorgan... |
1232 |
ieee80211_recalc_ps(local); |
cb17ed29a mac80211: parse r... |
1233 |
|
4b7afb52c mac80211: reorgan... |
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 |
if (sdata->vif.type == NL80211_IFTYPE_MONITOR || sdata->vif.type == NL80211_IFTYPE_AP_VLAN || local->ops->wake_tx_queue) { /* XXX: for AP_VLAN, actually track AP queues */ if (dev) netif_tx_start_all_queues(dev); } else if (dev) { unsigned long flags; int n_acs = IEEE80211_NUM_ACS; int ac; |
cf0277e71 mac80211: fix skb... |
1244 |
|
4b7afb52c mac80211: reorgan... |
1245 1246 |
if (local->hw.queues < IEEE80211_NUM_ACS) n_acs = 1; |
cf0277e71 mac80211: fix skb... |
1247 |
|
4b7afb52c mac80211: reorgan... |
1248 1249 1250 1251 1252 1253 |
spin_lock_irqsave(&local->queue_stop_reason_lock, flags); if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE || (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 && skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) { for (ac = 0; ac < n_acs; ac++) { int ac_queue = sdata->vif.hw_queue[ac]; |
cf0277e71 mac80211: fix skb... |
1254 |
|
4b7afb52c mac80211: reorgan... |
1255 1256 1257 1258 1259 1260 1261 |
if (local->queue_stop_reasons[ac_queue] == 0 && skb_queue_empty(&local->pending[ac_queue])) netif_start_subqueue(dev, ac); } } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); } |
587e729ec mac80211: convert... |
1262 |
|
4b7afb52c mac80211: reorgan... |
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 |
return 0; err_del_interface: drv_remove_interface(local, sdata); err_stop: if (!local->open_count) drv_stop(local); err_del_bss: sdata->bss = NULL; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { mutex_lock(&local->mtx); list_del(&sdata->u.vlan.list); mutex_unlock(&local->mtx); } /* might already be clear but that doesn't matter */ clear_bit(SDATA_STATE_RUNNING, &sdata->state); return res; } |
50ff477a8 mac80211: add 802... |
1280 |
|
5a490510b mac80211: use per... |
1281 1282 1283 |
static void ieee80211_if_free(struct net_device *dev) { free_percpu(dev->tstats); |
5a490510b mac80211: use per... |
1284 |
} |
587e729ec mac80211: convert... |
1285 1286 1287 |
static void ieee80211_if_setup(struct net_device *dev) { ether_setup(dev); |
550fd08c2 net: Audit driver... |
1288 |
dev->priv_flags &= ~IFF_TX_SKB_SHARING; |
587e729ec mac80211: convert... |
1289 |
dev->netdev_ops = &ieee80211_dataif_ops; |
cf124db56 net: Fix inconsis... |
1290 1291 |
dev->needs_free_netdev = true; dev->priv_destructor = ieee80211_if_free; |
587e729ec mac80211: convert... |
1292 |
} |
80a83cfc4 mac80211: skip ne... |
1293 1294 1295 1296 1297 |
static void ieee80211_if_setup_no_queue(struct net_device *dev) { ieee80211_if_setup(dev); dev->priv_flags |= IFF_NO_QUEUE; } |
1fa57d017 mac80211: use com... |
1298 1299 1300 1301 1302 1303 |
static void ieee80211_iface_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, work); struct ieee80211_local *local = sdata->local; struct sk_buff *skb; |
344eec67c mac80211: move bl... |
1304 |
struct sta_info *sta; |
1fa57d017 mac80211: use com... |
1305 1306 1307 |
if (!ieee80211_sdata_running(sdata)) return; |
fc58c47ef mac80211: process... |
1308 |
if (test_bit(SCAN_SW_SCANNING, &local->scanning)) |
1fa57d017 mac80211: use com... |
1309 |
return; |
4afaff176 mac80211: avoid r... |
1310 |
if (!ieee80211_can_run_worker(local)) |
1fa57d017 mac80211: use com... |
1311 1312 1313 1314 |
return; /* first process frames */ while ((skb = skb_dequeue(&sdata->skb_queue))) { |
bed7ee6e4 mac80211: always ... |
1315 |
struct ieee80211_mgmt *mgmt = (void *)skb->data; |
699cb58c8 mac80211: manage ... |
1316 1317 |
if (ieee80211_is_action(mgmt->frame_control) && mgmt->u.action.category == WLAN_CATEGORY_BACK) { |
bed7ee6e4 mac80211: always ... |
1318 |
int len = skb->len; |
bed7ee6e4 mac80211: always ... |
1319 |
|
a93e36443 mac80211: change ... |
1320 |
mutex_lock(&local->sta_mtx); |
875ae5f68 mac80211: fix agg... |
1321 |
sta = sta_info_get_bss(sdata, mgmt->sa); |
bed7ee6e4 mac80211: always ... |
1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 |
if (sta) { switch (mgmt->u.action.u.addba_req.action_code) { case WLAN_ACTION_ADDBA_REQ: ieee80211_process_addba_request( local, sta, mgmt, len); break; case WLAN_ACTION_ADDBA_RESP: ieee80211_process_addba_resp(local, sta, mgmt, len); break; case WLAN_ACTION_DELBA: ieee80211_process_delba(sdata, sta, mgmt, len); break; default: WARN_ON(1); break; } } |
a93e36443 mac80211: change ... |
1341 |
mutex_unlock(&local->sta_mtx); |
23a1f8d44 mac80211: process... |
1342 1343 1344 |
} else if (ieee80211_is_action(mgmt->frame_control) && mgmt->u.action.category == WLAN_CATEGORY_VHT) { switch (mgmt->u.action.u.vht_group_notif.action_code) { |
d2941df8f mac80211: recalcu... |
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 |
case WLAN_VHT_ACTION_OPMODE_NOTIF: { struct ieee80211_rx_status *status; enum nl80211_band band; u8 opmode; status = IEEE80211_SKB_RXCB(skb); band = status->band; opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; mutex_lock(&local->sta_mtx); sta = sta_info_get_bss(sdata, mgmt->sa); if (sta) ieee80211_vht_handle_opmode(sdata, sta, opmode, band); mutex_unlock(&local->sta_mtx); break; } |
23a1f8d44 mac80211: process... |
1365 1366 1367 1368 1369 1370 1371 |
case WLAN_VHT_ACTION_GROUPID_MGMT: ieee80211_process_mu_groups(sdata, mgmt); break; default: WARN_ON(1); break; } |
09a740ce3 mac80211: receive... |
1372 1373 1374 1375 1376 |
} else if (ieee80211_is_ext(mgmt->frame_control)) { if (sdata->vif.type == NL80211_IFTYPE_STATION) ieee80211_sta_rx_queued_ext(sdata, skb); else WARN_ON(1); |
344eec67c mac80211: move bl... |
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 |
} else if (ieee80211_is_data_qos(mgmt->frame_control)) { struct ieee80211_hdr *hdr = (void *)mgmt; /* * So the frame isn't mgmt, but frame_control * is at the right place anyway, of course, so * the if statement is correct. * * Warn if we have other data frame types here, * they must not get here. */ WARN_ON(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)); WARN_ON(!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); /* * This was a fragment of a frame, received while * a block-ack session was active. That cannot be * right, so terminate the session. */ |
a93e36443 mac80211: change ... |
1396 |
mutex_lock(&local->sta_mtx); |
875ae5f68 mac80211: fix agg... |
1397 |
sta = sta_info_get_bss(sdata, mgmt->sa); |
344eec67c mac80211: move bl... |
1398 |
if (sta) { |
a1f2ba04c mac80211: add get... |
1399 |
u16 tid = ieee80211_get_tid(hdr); |
344eec67c mac80211: move bl... |
1400 1401 1402 |
__ieee80211_stop_rx_ba_session( sta, tid, WLAN_BACK_RECIPIENT, |
53f73c09d mac80211: avoid t... |
1403 1404 |
WLAN_REASON_QSTA_REQUIRE_SETUP, true); |
344eec67c mac80211: move bl... |
1405 |
} |
a93e36443 mac80211: change ... |
1406 |
mutex_unlock(&local->sta_mtx); |
bed7ee6e4 mac80211: always ... |
1407 |
} else switch (sdata->vif.type) { |
1fa57d017 mac80211: use com... |
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 |
case NL80211_IFTYPE_STATION: ieee80211_sta_rx_queued_mgmt(sdata, skb); break; case NL80211_IFTYPE_ADHOC: ieee80211_ibss_rx_queued_mgmt(sdata, skb); break; case NL80211_IFTYPE_MESH_POINT: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; ieee80211_mesh_rx_queued_mgmt(sdata, skb); break; default: WARN(1, "frame for unexpected interface type"); |
1fa57d017 mac80211: use com... |
1421 1422 |
break; } |
36b3a628a mac80211: common ... |
1423 1424 |
kfree_skb(skb); |
1fa57d017 mac80211: use com... |
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 |
} /* then other type-dependent work */ switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: ieee80211_sta_work(sdata); break; case NL80211_IFTYPE_ADHOC: ieee80211_ibss_work(sdata); break; case NL80211_IFTYPE_MESH_POINT: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; ieee80211_mesh_work(sdata); break; |
239281f80 mac80211: 802.11p... |
1440 1441 1442 |
case NL80211_IFTYPE_OCB: ieee80211_ocb_work(sdata); break; |
1fa57d017 mac80211: use com... |
1443 1444 1445 1446 |
default: break; } } |
04ecd2578 mac80211: track n... |
1447 1448 1449 1450 1451 1452 1453 |
static void ieee80211_recalc_smps_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, recalc_smps); ieee80211_recalc_smps(sdata); } |
1fa57d017 mac80211: use com... |
1454 |
|
75636525f mac80211: revamp ... |
1455 1456 1457 1458 |
/* * Helper function to initialise an interface to a specific type. */ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, |
05c914fe3 mac80211: use nl8... |
1459 |
enum nl80211_iftype type) |
f0706e828 [MAC80211]: Add m... |
1460 |
{ |
239281f80 mac80211: 802.11p... |
1461 1462 |
static const u8 bssid_wildcard[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
75636525f mac80211: revamp ... |
1463 1464 1465 1466 1467 |
/* clear type-dependent union */ memset(&sdata->u, 0, sizeof(sdata->u)); /* and set some type-dependent values */ sdata->vif.type = type; |
2ca27bcff mac80211: add p2p... |
1468 |
sdata->vif.p2p = false; |
60719ffd7 cfg80211: show in... |
1469 |
sdata->wdev.iftype = type; |
75636525f mac80211: revamp ... |
1470 |
|
a621fa4d6 mac80211: allow c... |
1471 1472 |
sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); sdata->control_port_no_encrypt = false; |
7f3f96ced mac80211: handle ... |
1473 1474 |
sdata->control_port_over_nl80211 = false; sdata->control_port_no_preauth = false; |
2475b1cc0 mac80211: add gen... |
1475 |
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; |
d3a58df87 mac80211: set new... |
1476 |
sdata->vif.bss_conf.idle = true; |
db6d9e9e8 mac80211: Fix set... |
1477 |
sdata->vif.bss_conf.txpower = INT_MIN; /* unset */ |
a621fa4d6 mac80211: allow c... |
1478 |
|
b53be7920 mac80211: Add NoA... |
1479 |
sdata->noack_map = 0; |
f142c6b90 mac80211: support... |
1480 1481 1482 1483 1484 |
/* only monitor/p2p-device differ */ if (sdata->dev) { sdata->dev->netdev_ops = &ieee80211_dataif_ops; sdata->dev->type = ARPHRD_ETHER; } |
75636525f mac80211: revamp ... |
1485 |
|
35f20c14a mac80211: use com... |
1486 |
skb_queue_head_init(&sdata->skb_queue); |
1fa57d017 mac80211: use com... |
1487 |
INIT_WORK(&sdata->work, ieee80211_iface_work); |
04ecd2578 mac80211: track n... |
1488 |
INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); |
73da7d5ba mac80211: add cha... |
1489 |
INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work); |
484298ad1 mac80211: track a... |
1490 |
INIT_LIST_HEAD(&sdata->assigned_chanctx_list); |
e3afb9202 mac80211: track r... |
1491 |
INIT_LIST_HEAD(&sdata->reserved_chanctx_list); |
35f20c14a mac80211: use com... |
1492 |
|
75636525f mac80211: revamp ... |
1493 |
switch (type) { |
2ca27bcff mac80211: add p2p... |
1494 1495 1496 1497 |
case NL80211_IFTYPE_P2P_GO: type = NL80211_IFTYPE_AP; sdata->vif.type = type; sdata->vif.p2p = true; |
fc0561dc6 mac80211: Use fal... |
1498 |
fallthrough; |
05c914fe3 mac80211: use nl8... |
1499 |
case NL80211_IFTYPE_AP: |
d012a6051 mac80211: make cl... |
1500 |
skb_queue_head_init(&sdata->u.ap.ps.bc_buf); |
75636525f mac80211: revamp ... |
1501 |
INIT_LIST_HEAD(&sdata->u.ap.vlans); |
ad2d223aa mac80211: assign ... |
1502 |
sdata->vif.bss_conf.bssid = sdata->vif.addr; |
75636525f mac80211: revamp ... |
1503 |
break; |
2ca27bcff mac80211: add p2p... |
1504 1505 1506 1507 |
case NL80211_IFTYPE_P2P_CLIENT: type = NL80211_IFTYPE_STATION; sdata->vif.type = type; sdata->vif.p2p = true; |
fc0561dc6 mac80211: Use fal... |
1508 |
fallthrough; |
05c914fe3 mac80211: use nl8... |
1509 |
case NL80211_IFTYPE_STATION: |
ad2d223aa mac80211: assign ... |
1510 |
sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; |
9c6bd7901 mac80211: reorder... |
1511 |
ieee80211_sta_setup_sdata(sdata); |
472dbc45d mac80211: split o... |
1512 |
break; |
6e0bd6c35 cfg80211: 802.11p... |
1513 |
case NL80211_IFTYPE_OCB: |
239281f80 mac80211: 802.11p... |
1514 1515 |
sdata->vif.bss_conf.bssid = bssid_wildcard; ieee80211_ocb_setup_sdata(sdata); |
6e0bd6c35 cfg80211: 802.11p... |
1516 |
break; |
469002983 mac80211: split I... |
1517 |
case NL80211_IFTYPE_ADHOC: |
ad2d223aa mac80211: assign ... |
1518 |
sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
469002983 mac80211: split I... |
1519 1520 |
ieee80211_ibss_setup_sdata(sdata); break; |
05c914fe3 mac80211: use nl8... |
1521 |
case NL80211_IFTYPE_MESH_POINT: |
75636525f mac80211: revamp ... |
1522 1523 1524 |
if (ieee80211_vif_is_mesh(&sdata->vif)) ieee80211_mesh_init_sdata(sdata); break; |
05c914fe3 mac80211: use nl8... |
1525 |
case NL80211_IFTYPE_MONITOR: |
75636525f mac80211: revamp ... |
1526 |
sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
587e729ec mac80211: convert... |
1527 |
sdata->dev->netdev_ops = &ieee80211_monitorif_ops; |
d82121845 mac80211: refacto... |
1528 |
sdata->u.mntr.flags = MONITOR_FLAG_CONTROL | |
75636525f mac80211: revamp ... |
1529 1530 |
MONITOR_FLAG_OTHER_BSS; break; |
05c914fe3 mac80211: use nl8... |
1531 |
case NL80211_IFTYPE_WDS: |
ad2d223aa mac80211: assign ... |
1532 1533 |
sdata->vif.bss_conf.bssid = NULL; break; |
167e33f4f mac80211: Impleme... |
1534 1535 1536 1537 1538 |
case NL80211_IFTYPE_NAN: idr_init(&sdata->u.nan.function_inst_ids); spin_lock_init(&sdata->u.nan.func_lock); sdata->vif.bss_conf.bssid = sdata->vif.addr; break; |
05c914fe3 mac80211: use nl8... |
1539 |
case NL80211_IFTYPE_AP_VLAN: |
98104fded cfg80211: add P2P... |
1540 |
case NL80211_IFTYPE_P2P_DEVICE: |
ad2d223aa mac80211: assign ... |
1541 |
sdata->vif.bss_conf.bssid = sdata->vif.addr; |
f142c6b90 mac80211: support... |
1542 |
break; |
05c914fe3 mac80211: use nl8... |
1543 |
case NL80211_IFTYPE_UNSPECIFIED: |
2e161f78e cfg80211/mac80211... |
1544 |
case NUM_NL80211_IFTYPES: |
c7976f527 mac80211: remove ... |
1545 |
WARN_ON(1); |
75636525f mac80211: revamp ... |
1546 1547 1548 1549 1550 |
break; } ieee80211_debugfs_add_netdev(sdata); } |
34d4bc4d4 mac80211: support... |
1551 1552 1553 1554 1555 |
static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype type) { struct ieee80211_local *local = sdata->local; int ret, err; |
2ca27bcff mac80211: add p2p... |
1556 1557 |
enum nl80211_iftype internal_type = type; bool p2p = false; |
34d4bc4d4 mac80211: support... |
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 |
ASSERT_RTNL(); if (!local->ops->change_interface) return -EBUSY; switch (sdata->vif.type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: |
239281f80 mac80211: 802.11p... |
1568 |
case NL80211_IFTYPE_OCB: |
34d4bc4d4 mac80211: support... |
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 |
/* * Could maybe also all others here? * Just not sure how that interacts * with the RX/config path e.g. for * mesh. */ break; default: return -EBUSY; } switch (type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: |
239281f80 mac80211: 802.11p... |
1584 |
case NL80211_IFTYPE_OCB: |
34d4bc4d4 mac80211: support... |
1585 1586 1587 1588 1589 1590 1591 |
/* * Could probably support everything * but WDS here (WDS do_open can fail * under memory pressure, which this * code isn't prepared to handle). */ break; |
2ca27bcff mac80211: add p2p... |
1592 1593 1594 1595 1596 1597 1598 1599 |
case NL80211_IFTYPE_P2P_CLIENT: p2p = true; internal_type = NL80211_IFTYPE_STATION; break; case NL80211_IFTYPE_P2P_GO: p2p = true; internal_type = NL80211_IFTYPE_AP; break; |
34d4bc4d4 mac80211: support... |
1600 1601 1602 |
default: return -EBUSY; } |
2ca27bcff mac80211: add p2p... |
1603 |
ret = ieee80211_check_concurrent_iface(sdata, internal_type); |
34d4bc4d4 mac80211: support... |
1604 1605 1606 1607 |
if (ret) return ret; ieee80211_do_stop(sdata, false); |
f142c6b90 mac80211: support... |
1608 |
ieee80211_teardown_sdata(sdata); |
34d4bc4d4 mac80211: support... |
1609 |
|
6aea26ce5 mac80211: rework ... |
1610 |
ieee80211_set_sdata_offload_flags(sdata); |
2ca27bcff mac80211: add p2p... |
1611 |
ret = drv_change_interface(local, sdata, internal_type, p2p); |
34d4bc4d4 mac80211: support... |
1612 |
if (ret) |
a98655387 mac80211: fix cha... |
1613 |
type = ieee80211_vif_type_p2p(&sdata->vif); |
34d4bc4d4 mac80211: support... |
1614 |
|
3a25a8c8b mac80211: add imp... |
1615 1616 1617 1618 1619 |
/* * Ignore return value here, there's not much we can do since * the driver changed the interface type internally already. * The warnings will hopefully make driver authors fix it :-) */ |
a98655387 mac80211: fix cha... |
1620 |
ieee80211_check_queues(sdata, type); |
3a25a8c8b mac80211: add imp... |
1621 |
|
34d4bc4d4 mac80211: support... |
1622 |
ieee80211_setup_sdata(sdata, type); |
6aea26ce5 mac80211: rework ... |
1623 |
ieee80211_set_vif_encap_ops(sdata); |
34d4bc4d4 mac80211: support... |
1624 |
|
f142c6b90 mac80211: support... |
1625 |
err = ieee80211_do_open(&sdata->wdev, false); |
34d4bc4d4 mac80211: support... |
1626 1627 1628 1629 |
WARN(err, "type change: do_open returned %d", err); return ret; } |
f3947e2df mac80211: push in... |
1630 |
int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
05c914fe3 mac80211: use nl8... |
1631 |
enum nl80211_iftype type) |
75636525f mac80211: revamp ... |
1632 |
{ |
34d4bc4d4 mac80211: support... |
1633 |
int ret; |
f3947e2df mac80211: push in... |
1634 |
ASSERT_RTNL(); |
2ca27bcff mac80211: add p2p... |
1635 |
if (type == ieee80211_vif_type_p2p(&sdata->vif)) |
f3947e2df mac80211: push in... |
1636 |
return 0; |
34d4bc4d4 mac80211: support... |
1637 1638 1639 1640 1641 1642 |
if (ieee80211_sdata_running(sdata)) { ret = ieee80211_runtime_change_iftype(sdata, type); if (ret) return ret; } else { /* Purge and reset type-dependent state. */ |
f142c6b90 mac80211: support... |
1643 |
ieee80211_teardown_sdata(sdata); |
34d4bc4d4 mac80211: support... |
1644 1645 |
ieee80211_setup_sdata(sdata, type); } |
75636525f mac80211: revamp ... |
1646 1647 |
/* reset some values that shouldn't be kept across type changes */ |
9bc383de3 cfg80211: introdu... |
1648 1649 |
if (type == NL80211_IFTYPE_STATION) sdata->u.mgd.use_4addr = false; |
f3947e2df mac80211: push in... |
1650 1651 |
return 0; |
f0706e828 [MAC80211]: Add m... |
1652 |
} |
fa9029f8c mac80211: use dif... |
1653 |
static void ieee80211_assign_perm_addr(struct ieee80211_local *local, |
f142c6b90 mac80211: support... |
1654 |
u8 *perm_addr, enum nl80211_iftype type) |
fa9029f8c mac80211: use dif... |
1655 1656 1657 1658 1659 1660 1661 1662 |
{ struct ieee80211_sub_if_data *sdata; u64 mask, start, addr, val, inc; u8 *m; u8 tmp_addr[ETH_ALEN]; int i; /* default ... something at least */ |
f142c6b90 mac80211: support... |
1663 |
memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
fa9029f8c mac80211: use dif... |
1664 1665 1666 1667 |
if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && local->hw.wiphy->n_addresses <= 1) return; |
fa9029f8c mac80211: use dif... |
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 |
mutex_lock(&local->iflist_mtx); switch (type) { case NL80211_IFTYPE_MONITOR: /* doesn't matter */ break; case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_AP_VLAN: /* match up with an AP interface */ list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP) continue; |
f142c6b90 mac80211: support... |
1680 |
memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); |
fa9029f8c mac80211: use dif... |
1681 1682 1683 1684 |
break; } /* keep default if no AP interface present */ break; |
6d71117a2 mac80211: add IEE... |
1685 1686 |
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: |
30686bf7f mac80211: convert... |
1687 |
if (ieee80211_hw_check(&local->hw, P2P_DEV_ADDR_FOR_INTF)) { |
6d71117a2 mac80211: add IEE... |
1688 1689 1690 1691 1692 1693 1694 1695 1696 |
list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) continue; if (!ieee80211_sdata_running(sdata)) continue; memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); goto out_unlock; } } |
fc0561dc6 mac80211: Use fal... |
1697 |
fallthrough; |
fa9029f8c mac80211: use dif... |
1698 1699 1700 1701 1702 1703 |
default: /* assign a new address if possible -- try n_addresses first */ for (i = 0; i < local->hw.wiphy->n_addresses; i++) { bool used = false; list_for_each_entry(sdata, &local->interfaces, list) { |
496d7e8ea mac8011: slight o... |
1704 1705 |
if (ether_addr_equal(local->hw.wiphy->addresses[i].addr, sdata->vif.addr)) { |
fa9029f8c mac80211: use dif... |
1706 1707 1708 1709 1710 1711 |
used = true; break; } } if (!used) { |
f142c6b90 mac80211: support... |
1712 |
memcpy(perm_addr, |
fa9029f8c mac80211: use dif... |
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 |
local->hw.wiphy->addresses[i].addr, ETH_ALEN); break; } } /* try mask if available */ if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) break; m = local->hw.wiphy->addr_mask; mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { /* not a contiguous mask ... not handled now! */ |
bdcbd8e0e mac80211: clean u... |
1730 1731 |
pr_info("not contiguous "); |
fa9029f8c mac80211: use dif... |
1732 1733 |
break; } |
ac20976dc mac80211: Allow s... |
1734 1735 1736 1737 |
/* * Pick address of existing interface in case user changed * MAC address manually, default to perm_addr. */ |
fa9029f8c mac80211: use dif... |
1738 |
m = local->hw.wiphy->perm_addr; |
ac20976dc mac80211: Allow s... |
1739 1740 1741 1742 1743 1744 |
list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) continue; m = sdata->vif.addr; break; } |
fa9029f8c mac80211: use dif... |
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 |
start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); inc = 1ULL<<__ffs64(mask); val = (start & mask); addr = (start & ~mask) | (val & mask); do { bool used = false; tmp_addr[5] = addr >> 0*8; tmp_addr[4] = addr >> 1*8; tmp_addr[3] = addr >> 2*8; tmp_addr[2] = addr >> 3*8; tmp_addr[1] = addr >> 4*8; tmp_addr[0] = addr >> 5*8; val += inc; list_for_each_entry(sdata, &local->interfaces, list) { |
496d7e8ea mac8011: slight o... |
1765 |
if (ether_addr_equal(tmp_addr, sdata->vif.addr)) { |
fa9029f8c mac80211: use dif... |
1766 1767 1768 1769 1770 1771 |
used = true; break; } } if (!used) { |
f142c6b90 mac80211: support... |
1772 |
memcpy(perm_addr, tmp_addr, ETH_ALEN); |
fa9029f8c mac80211: use dif... |
1773 1774 1775 1776 1777 1778 1779 |
break; } addr = (start & ~mask) | (val & mask); } while (addr != start); break; } |
6d71117a2 mac80211: add IEE... |
1780 |
out_unlock: |
fa9029f8c mac80211: use dif... |
1781 1782 |
mutex_unlock(&local->iflist_mtx); } |
3e122be08 mac80211: make ma... |
1783 |
int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
6bab2e19c cfg80211: pass na... |
1784 |
unsigned char name_assign_type, |
84efbb84c cfg80211: use wir... |
1785 |
struct wireless_dev **new_wdev, enum nl80211_iftype type, |
ee3858551 mac80211: mesh da... |
1786 |
struct vif_params *params) |
f0706e828 [MAC80211]: Add m... |
1787 |
{ |
f142c6b90 mac80211: support... |
1788 |
struct net_device *ndev = NULL; |
f0706e828 [MAC80211]: Add m... |
1789 |
struct ieee80211_sub_if_data *sdata = NULL; |
ba8c3d6f1 mac80211: add an ... |
1790 |
struct txq_info *txqi; |
80a83cfc4 mac80211: skip ne... |
1791 |
void (*if_setup)(struct net_device *dev); |
75636525f mac80211: revamp ... |
1792 |
int ret, i; |
ded81f6ba mac80211: decoupl... |
1793 |
int txqs = 1; |
f0706e828 [MAC80211]: Add m... |
1794 1795 |
ASSERT_RTNL(); |
75636525f mac80211: revamp ... |
1796 |
|
708d50edb mac80211: add boi... |
1797 |
if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) { |
f142c6b90 mac80211: support... |
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 |
struct wireless_dev *wdev; sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); if (!sdata) return -ENOMEM; wdev = &sdata->wdev; sdata->dev = NULL; strlcpy(sdata->name, name, IFNAMSIZ); ieee80211_assign_perm_addr(local, wdev->address, type); memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); } else { |
ba8c3d6f1 mac80211: add an ... |
1811 1812 1813 |
int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size, sizeof(void *)); int txq_size = 0; |
79af1f866 mac80211: avoid a... |
1814 1815 |
if (local->ops->wake_tx_queue && type != NL80211_IFTYPE_AP_VLAN && |
8105f9b8a mac80211: allocat... |
1816 1817 |
(type != NL80211_IFTYPE_MONITOR || (params->flags & MONITOR_FLAG_ACTIVE))) |
ba8c3d6f1 mac80211: add an ... |
1818 1819 |
txq_size += sizeof(struct txq_info) + local->hw.txq_data_size; |
dbd50a851 mac80211: only al... |
1820 |
if (local->ops->wake_tx_queue) { |
80a83cfc4 mac80211: skip ne... |
1821 |
if_setup = ieee80211_if_setup_no_queue; |
dbd50a851 mac80211: only al... |
1822 |
} else { |
80a83cfc4 mac80211: skip ne... |
1823 |
if_setup = ieee80211_if_setup; |
dbd50a851 mac80211: only al... |
1824 1825 1826 |
if (local->hw.queues >= IEEE80211_NUM_ACS) txqs = IEEE80211_NUM_ACS; } |
f142c6b90 mac80211: support... |
1827 |
|
ba8c3d6f1 mac80211: add an ... |
1828 |
ndev = alloc_netdev_mqs(size + txq_size, |
6bab2e19c cfg80211: pass na... |
1829 |
name, name_assign_type, |
80a83cfc4 mac80211: skip ne... |
1830 |
if_setup, txqs, 1); |
f142c6b90 mac80211: support... |
1831 1832 |
if (!ndev) return -ENOMEM; |
1f6e0baa7 mac80211: allow s... |
1833 1834 1835 |
if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len) ndev->tx_queue_len = local->hw.wiphy->tx_queue_len; |
f142c6b90 mac80211: support... |
1836 |
dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
5a490510b mac80211: use per... |
1837 1838 1839 1840 1841 |
ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!ndev->tstats) { free_netdev(ndev); return -ENOMEM; } |
f142c6b90 mac80211: support... |
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 |
ndev->needed_headroom = local->tx_headroom + 4*6 /* four MAC addresses */ + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ + 6 /* mesh */ + 8 /* rfc1042/bridge tunnel */ - ETH_HLEN /* ethernet hard_header_len */ + IEEE80211_ENCRYPT_HEADROOM; ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; ret = dev_alloc_name(ndev, ndev->name); if (ret < 0) { |
e6436be21 mac80211: fix sta... |
1853 |
ieee80211_if_free(ndev); |
c7a61cba7 mac80211: free ne... |
1854 |
free_netdev(ndev); |
f142c6b90 mac80211: support... |
1855 1856 1857 1858 |
return ret; } ieee80211_assign_perm_addr(local, ndev->perm_addr, type); |
dd665d23c mac80211: never p... |
1859 |
if (is_valid_ether_addr(params->macaddr)) |
b5dfae020 mac80211: support... |
1860 1861 1862 |
memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN); else memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); |
f142c6b90 mac80211: support... |
1863 1864 1865 1866 1867 1868 1869 |
SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */ sdata = netdev_priv(ndev); ndev->ieee80211_ptr = &sdata->wdev; memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); memcpy(sdata->name, ndev->name, IFNAMSIZ); |
ba8c3d6f1 mac80211: add an ... |
1870 1871 |
if (txq_size) { txqi = netdev_priv(ndev) + size; |
fa962b921 mac80211: impleme... |
1872 |
ieee80211_txq_init(sdata, NULL, txqi, 0); |
ba8c3d6f1 mac80211: add an ... |
1873 |
} |
f142c6b90 mac80211: support... |
1874 1875 |
sdata->dev = ndev; } |
75636525f mac80211: revamp ... |
1876 1877 |
/* initialise type-independent data */ |
f0706e828 [MAC80211]: Add m... |
1878 |
sdata->wdev.wiphy = local->hw.wiphy; |
f0706e828 [MAC80211]: Add m... |
1879 |
sdata->local = local; |
75636525f mac80211: revamp ... |
1880 1881 1882 1883 1884 |
for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) skb_queue_head_init(&sdata->fragments[i].skb_list); INIT_LIST_HEAD(&sdata->key_list); |
164eb02d0 mac80211: add rad... |
1885 1886 |
INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, ieee80211_dfs_cac_timer_work); |
8d1f7ecd2 mac80211: defer t... |
1887 1888 |
INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, ieee80211_delayed_tailroom_dec); |
97f97b1f5 mac80211: fix sta... |
1889 |
|
57fbcce37 cfg80211: remove ... |
1890 |
for (i = 0; i < NUM_NL80211_BANDS; i++) { |
37eb0b164 cfg80211/mac80211... |
1891 1892 1893 1894 |
struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[i]; sdata->rc_rateidx_mask[i] = sband ? (1 << sband->n_bitrates) - 1 : 0; |
b119ad6e7 mac80211: add rat... |
1895 1896 1897 |
if (sband) { __le16 cap; u16 *vht_rate_mask; |
19468413e mac80211: add sup... |
1898 1899 1900 |
memcpy(sdata->rc_rateidx_mcs_mask[i], sband->ht_cap.mcs.rx_mask, sizeof(sdata->rc_rateidx_mcs_mask[i])); |
b119ad6e7 mac80211: add rat... |
1901 1902 1903 1904 1905 |
cap = sband->vht_cap.vht_mcs.rx_mcs_map; vht_rate_mask = sdata->rc_rateidx_vht_mcs_mask[i]; ieee80211_get_vht_mask_from_cap(cap, vht_rate_mask); } else { |
19468413e mac80211: add sup... |
1906 1907 |
memset(sdata->rc_rateidx_mcs_mask[i], 0, sizeof(sdata->rc_rateidx_mcs_mask[i])); |
b119ad6e7 mac80211: add rat... |
1908 1909 1910 |
memset(sdata->rc_rateidx_vht_mcs_mask[i], 0, sizeof(sdata->rc_rateidx_vht_mcs_mask[i])); } |
37eb0b164 cfg80211/mac80211... |
1911 |
} |
75636525f mac80211: revamp ... |
1912 |
|
3a25a8c8b mac80211: add imp... |
1913 |
ieee80211_set_default_queues(sdata); |
1ea6f9c0d mac80211: handle ... |
1914 1915 |
sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; sdata->user_power_level = local->user_power_level; |
2475b1cc0 mac80211: add gen... |
1916 |
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; |
75636525f mac80211: revamp ... |
1917 1918 |
/* setup type-dependent data */ ieee80211_setup_sdata(sdata, type); |
f0706e828 [MAC80211]: Add m... |
1919 |
|
f142c6b90 mac80211: support... |
1920 |
if (ndev) { |
dd665d23c mac80211: never p... |
1921 1922 1923 |
ndev->ieee80211_ptr->use_4addr = params->use_4addr; if (type == NL80211_IFTYPE_STATION) sdata->u.mgd.use_4addr = params->use_4addr; |
9bc383de3 cfg80211: introdu... |
1924 |
|
f142c6b90 mac80211: support... |
1925 |
ndev->features |= local->hw.netdev_features; |
07b83d2ec mac80211: allow c... |
1926 1927 |
ndev->hw_features |= ndev->features & MAC80211_SUPPORTED_FEATURES_TX; |
72d787285 mac80211: allow l... |
1928 |
|
b7ffbd7ef cfg80211: make et... |
1929 |
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops); |
9c22b4a34 net: use core MTU... |
1930 1931 |
/* MTU range: 256 - 2304 */ ndev->min_mtu = 256; |
06354665f mac80211: allow d... |
1932 |
ndev->max_mtu = local->hw.max_mtu; |
9c22b4a34 net: use core MTU... |
1933 |
|
f142c6b90 mac80211: support... |
1934 1935 |
ret = register_netdevice(ndev); if (ret) { |
cf124db56 net: Fix inconsis... |
1936 |
free_netdev(ndev); |
f142c6b90 mac80211: support... |
1937 1938 1939 |
return ret; } } |
f0706e828 [MAC80211]: Add m... |
1940 |
|
c771c9d8d mac80211: add int... |
1941 |
mutex_lock(&local->iflist_mtx); |
79010420c [PATCH] mac80211:... |
1942 |
list_add_tail_rcu(&sdata->list, &local->interfaces); |
c771c9d8d mac80211: add int... |
1943 |
mutex_unlock(&local->iflist_mtx); |
79010420c [PATCH] mac80211:... |
1944 |
|
84efbb84c cfg80211: use wir... |
1945 1946 |
if (new_wdev) *new_wdev = &sdata->wdev; |
f0706e828 [MAC80211]: Add m... |
1947 |
|
f0706e828 [MAC80211]: Add m... |
1948 |
return 0; |
f0706e828 [MAC80211]: Add m... |
1949 |
} |
f698d856f replace net_devic... |
1950 |
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) |
f0706e828 [MAC80211]: Add m... |
1951 |
{ |
f0706e828 [MAC80211]: Add m... |
1952 |
ASSERT_RTNL(); |
11a843b7e [MAC80211]: rewor... |
1953 |
|
c771c9d8d mac80211: add int... |
1954 |
mutex_lock(&sdata->local->iflist_mtx); |
75636525f mac80211: revamp ... |
1955 |
list_del_rcu(&sdata->list); |
c771c9d8d mac80211: add int... |
1956 |
mutex_unlock(&sdata->local->iflist_mtx); |
f1267cf3c mac80211: Fix ker... |
1957 1958 |
if (sdata->vif.txq) ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq)); |
75636525f mac80211: revamp ... |
1959 |
synchronize_rcu(); |
f142c6b90 mac80211: support... |
1960 1961 1962 1963 1964 |
if (sdata->dev) { unregister_netdevice(sdata->dev); } else { cfg80211_unregister_wdev(&sdata->wdev); |
835112b28 mac80211: don't t... |
1965 |
ieee80211_teardown_sdata(sdata); |
f142c6b90 mac80211: support... |
1966 1967 1968 1969 1970 1971 1972 1973 1974 |
kfree(sdata); } } void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) { if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) return; ieee80211_do_stop(sdata, true); |
f0706e828 [MAC80211]: Add m... |
1975 |
} |
75636525f mac80211: revamp ... |
1976 |
void ieee80211_remove_interfaces(struct ieee80211_local *local) |
f0706e828 [MAC80211]: Add m... |
1977 |
{ |
75636525f mac80211: revamp ... |
1978 |
struct ieee80211_sub_if_data *sdata, *tmp; |
efe117ab8 mac80211: Speedup... |
1979 |
LIST_HEAD(unreg_list); |
f142c6b90 mac80211: support... |
1980 |
LIST_HEAD(wdev_list); |
f0706e828 [MAC80211]: Add m... |
1981 1982 |
ASSERT_RTNL(); |
d8d9008cf mac80211: shut do... |
1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 |
/* Before destroying the interfaces, make sure they're all stopped so * that the hardware is stopped. Otherwise, the driver might still be * iterating the interfaces during the shutdown, e.g. from a worker * or from RX processing or similar, and if it does so (using atomic * iteration) while we're manipulating the list, the iteration will * crash. * * After this, the hardware should be stopped and the driver should * have stopped all of its activities, so that we can do RCU-unaware * manipulations of the interface list below. |
c8aa22db0 mac80211: close A... |
1993 |
*/ |
d8d9008cf mac80211: shut do... |
1994 1995 1996 1997 1998 |
cfg80211_shutdown_all_interfaces(local->hw.wiphy); WARN(local->open_count, "%s: open count remains %d ", wiphy_name(local->hw.wiphy), local->open_count); |
c8aa22db0 mac80211: close A... |
1999 |
|
a50e5fb8d mac80211: fix a k... |
2000 |
ieee80211_txq_teardown_flows(local); |
efe117ab8 mac80211: Speedup... |
2001 |
mutex_lock(&local->iflist_mtx); |
75636525f mac80211: revamp ... |
2002 2003 |
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_del(&sdata->list); |
c771c9d8d mac80211: add int... |
2004 |
|
f142c6b90 mac80211: support... |
2005 2006 2007 2008 |
if (sdata->dev) unregister_netdevice_queue(sdata->dev, &unreg_list); else list_add(&sdata->list, &wdev_list); |
f0706e828 [MAC80211]: Add m... |
2009 |
} |
efe117ab8 mac80211: Speedup... |
2010 2011 |
mutex_unlock(&local->iflist_mtx); unregister_netdevice_many(&unreg_list); |
f142c6b90 mac80211: support... |
2012 2013 2014 2015 2016 2017 |
list_for_each_entry_safe(sdata, tmp, &wdev_list, list) { list_del(&sdata->list); cfg80211_unregister_wdev(&sdata->wdev); kfree(sdata); } |
f0706e828 [MAC80211]: Add m... |
2018 |
} |
5cff20e6c mac80211: tell dr... |
2019 |
|
47846c9b0 mac80211: reduce ... |
2020 |
static int netdev_notify(struct notifier_block *nb, |
351638e7d net: pass info st... |
2021 |
unsigned long state, void *ptr) |
47846c9b0 mac80211: reduce ... |
2022 |
{ |
351638e7d net: pass info st... |
2023 |
struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
47846c9b0 mac80211: reduce ... |
2024 2025 2026 |
struct ieee80211_sub_if_data *sdata; if (state != NETDEV_CHANGENAME) |
8bd811aa6 mac80211: change ... |
2027 |
return NOTIFY_DONE; |
47846c9b0 mac80211: reduce ... |
2028 2029 |
if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) |
8bd811aa6 mac80211: change ... |
2030 |
return NOTIFY_DONE; |
47846c9b0 mac80211: reduce ... |
2031 2032 |
if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) |
8bd811aa6 mac80211: change ... |
2033 |
return NOTIFY_DONE; |
47846c9b0 mac80211: reduce ... |
2034 2035 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2f5265e6e mac80211: fix net... |
2036 |
memcpy(sdata->name, dev->name, IFNAMSIZ); |
47846c9b0 mac80211: reduce ... |
2037 |
ieee80211_debugfs_rename_netdev(sdata); |
8bd811aa6 mac80211: change ... |
2038 2039 |
return NOTIFY_OK; |
47846c9b0 mac80211: reduce ... |
2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 |
} static struct notifier_block mac80211_netdev_notifier = { .notifier_call = netdev_notify, }; int ieee80211_iface_init(void) { return register_netdevice_notifier(&mac80211_netdev_notifier); } void ieee80211_iface_exit(void) { unregister_netdevice_notifier(&mac80211_netdev_notifier); } |
72f15d53f mac80211: filter ... |
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 |
void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata) { if (sdata->vif.type == NL80211_IFTYPE_AP) atomic_inc(&sdata->u.ap.num_mcast_sta); else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) atomic_inc(&sdata->u.vlan.num_mcast_sta); } void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata) { if (sdata->vif.type == NL80211_IFTYPE_AP) atomic_dec(&sdata->u.ap.num_mcast_sta); else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) atomic_dec(&sdata->u.vlan.num_mcast_sta); } |