diff options
author | David S. Miller <davem@davemloft.net> | 2015-05-09 17:27:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-09 17:27:25 -0400 |
commit | 0e00a0f73f9c7f5e9f02d064ed0165a3aeeb2de5 (patch) | |
tree | 5511eef8907c8b00985d74d8583c5253604ddb2e /net | |
parent | 82ae9c6060c6dbaf103273a5c51b8f58b951d9a2 (diff) | |
parent | bbbe8c8c596b3784a2ed08772900e827f8ba72c5 (diff) |
Merge tag 'mac80211-next-for-davem-2015-05-06' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says:
====================
Lots of updates for net-next for this cycle. As usual, we have
a lot of small fixes and cleanups, the bigger items are:
* proper mac80211 rate control locking, to fix some random crashes
(this required changing other locking as well)
* mac80211 "fast-xmit", a mechanism to reduce, in most cases, the
amount of code we execute while going from ndo_start_xmit() to
the driver
* this also clears the way for properly supporting S/G and checksum
and segmentation offloads
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/Kconfig | 16 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 117 | ||||
-rw-r--r-- | net/mac80211/chan.c | 6 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 74 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 85 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 11 | ||||
-rw-r--r-- | net/mac80211/ethtool.c | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 35 | ||||
-rw-r--r-- | net/mac80211/iface.c | 64 | ||||
-rw-r--r-- | net/mac80211/key.c | 12 | ||||
-rw-r--r-- | net/mac80211/key.h | 3 | ||||
-rw-r--r-- | net/mac80211/led.c | 256 | ||||
-rw-r--r-- | net/mac80211/led.h | 44 | ||||
-rw-r--r-- | net/mac80211/main.c | 15 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 37 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 57 | ||||
-rw-r--r-- | net/mac80211/rate.c | 8 | ||||
-rw-r--r-- | net/mac80211/rate.h | 14 | ||||
-rw-r--r-- | net/mac80211/rx.c | 201 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 10 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 41 | ||||
-rw-r--r-- | net/mac80211/status.c | 28 | ||||
-rw-r--r-- | net/mac80211/trace.h | 42 | ||||
-rw-r--r-- | net/mac80211/tx.c | 528 | ||||
-rw-r--r-- | net/wireless/chan.c | 65 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 7 | ||||
-rw-r--r-- | net/wireless/reg.c | 4 |
27 files changed, 1215 insertions, 568 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 64a012a0c6e5..086de496a4c1 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -302,6 +302,20 @@ config MAC80211_DEBUG_COUNTERS | |||
302 | ---help--- | 302 | ---help--- |
303 | Selecting this option causes mac80211 to keep additional | 303 | Selecting this option causes mac80211 to keep additional |
304 | and very verbose statistics about TX and RX handler use | 304 | and very verbose statistics about TX and RX handler use |
305 | and show them in debugfs. | 305 | as well as a few selected dot11 counters. These will be |
306 | exposed in debugfs. | ||
307 | |||
308 | Note that some of the counters are not concurrency safe | ||
309 | and may thus not always be accurate. | ||
306 | 310 | ||
307 | If unsure, say N. | 311 | If unsure, say N. |
312 | |||
313 | config MAC80211_STA_HASH_MAX_SIZE | ||
314 | int "Station hash table maximum size" if MAC80211_DEBUG_MENU | ||
315 | default 0 | ||
316 | ---help--- | ||
317 | Setting this option to a low value (e.g. 4) allows testing the | ||
318 | hash table with collisions relatively deterministically (just | ||
319 | connect more stations than the number selected here.) | ||
320 | |||
321 | If unsure, leave the default of 0. | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 265e42721a66..3469bbdc891c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -137,6 +137,9 @@ static int ieee80211_set_noack_map(struct wiphy *wiphy, | |||
137 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 137 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
138 | 138 | ||
139 | sdata->noack_map = noack_map; | 139 | sdata->noack_map = noack_map; |
140 | |||
141 | ieee80211_check_fast_xmit_iface(sdata); | ||
142 | |||
140 | return 0; | 143 | return 0; |
141 | } | 144 | } |
142 | 145 | ||
@@ -309,6 +312,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
309 | u32 iv32; | 312 | u32 iv32; |
310 | u16 iv16; | 313 | u16 iv16; |
311 | int err = -ENOENT; | 314 | int err = -ENOENT; |
315 | struct ieee80211_key_seq kseq = {}; | ||
312 | 316 | ||
313 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 317 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
314 | 318 | ||
@@ -339,10 +343,12 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
339 | iv32 = key->u.tkip.tx.iv32; | 343 | iv32 = key->u.tkip.tx.iv32; |
340 | iv16 = key->u.tkip.tx.iv16; | 344 | iv16 = key->u.tkip.tx.iv16; |
341 | 345 | ||
342 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 346 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
343 | drv_get_tkip_seq(sdata->local, | 347 | !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
344 | key->conf.hw_key_idx, | 348 | drv_get_key_seq(sdata->local, key, &kseq); |
345 | &iv32, &iv16); | 349 | iv32 = kseq.tkip.iv32; |
350 | iv16 = kseq.tkip.iv16; | ||
351 | } | ||
346 | 352 | ||
347 | seq[0] = iv16 & 0xff; | 353 | seq[0] = iv16 & 0xff; |
348 | seq[1] = (iv16 >> 8) & 0xff; | 354 | seq[1] = (iv16 >> 8) & 0xff; |
@@ -355,52 +361,85 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
355 | break; | 361 | break; |
356 | case WLAN_CIPHER_SUITE_CCMP: | 362 | case WLAN_CIPHER_SUITE_CCMP: |
357 | case WLAN_CIPHER_SUITE_CCMP_256: | 363 | case WLAN_CIPHER_SUITE_CCMP_256: |
358 | pn64 = atomic64_read(&key->u.ccmp.tx_pn); | 364 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
359 | seq[0] = pn64; | 365 | !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
360 | seq[1] = pn64 >> 8; | 366 | drv_get_key_seq(sdata->local, key, &kseq); |
361 | seq[2] = pn64 >> 16; | 367 | memcpy(seq, kseq.ccmp.pn, 6); |
362 | seq[3] = pn64 >> 24; | 368 | } else { |
363 | seq[4] = pn64 >> 32; | 369 | pn64 = atomic64_read(&key->u.ccmp.tx_pn); |
364 | seq[5] = pn64 >> 40; | 370 | seq[0] = pn64; |
371 | seq[1] = pn64 >> 8; | ||
372 | seq[2] = pn64 >> 16; | ||
373 | seq[3] = pn64 >> 24; | ||
374 | seq[4] = pn64 >> 32; | ||
375 | seq[5] = pn64 >> 40; | ||
376 | } | ||
365 | params.seq = seq; | 377 | params.seq = seq; |
366 | params.seq_len = 6; | 378 | params.seq_len = 6; |
367 | break; | 379 | break; |
368 | case WLAN_CIPHER_SUITE_AES_CMAC: | 380 | case WLAN_CIPHER_SUITE_AES_CMAC: |
369 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: | 381 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
370 | pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); | 382 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
371 | seq[0] = pn64; | 383 | !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
372 | seq[1] = pn64 >> 8; | 384 | drv_get_key_seq(sdata->local, key, &kseq); |
373 | seq[2] = pn64 >> 16; | 385 | memcpy(seq, kseq.aes_cmac.pn, 6); |
374 | seq[3] = pn64 >> 24; | 386 | } else { |
375 | seq[4] = pn64 >> 32; | 387 | pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); |
376 | seq[5] = pn64 >> 40; | 388 | seq[0] = pn64; |
389 | seq[1] = pn64 >> 8; | ||
390 | seq[2] = pn64 >> 16; | ||
391 | seq[3] = pn64 >> 24; | ||
392 | seq[4] = pn64 >> 32; | ||
393 | seq[5] = pn64 >> 40; | ||
394 | } | ||
377 | params.seq = seq; | 395 | params.seq = seq; |
378 | params.seq_len = 6; | 396 | params.seq_len = 6; |
379 | break; | 397 | break; |
380 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: | 398 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: |
381 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: | 399 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: |
382 | pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); | 400 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
383 | seq[0] = pn64; | 401 | !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
384 | seq[1] = pn64 >> 8; | 402 | drv_get_key_seq(sdata->local, key, &kseq); |
385 | seq[2] = pn64 >> 16; | 403 | memcpy(seq, kseq.aes_gmac.pn, 6); |
386 | seq[3] = pn64 >> 24; | 404 | } else { |
387 | seq[4] = pn64 >> 32; | 405 | pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); |
388 | seq[5] = pn64 >> 40; | 406 | seq[0] = pn64; |
407 | seq[1] = pn64 >> 8; | ||
408 | seq[2] = pn64 >> 16; | ||
409 | seq[3] = pn64 >> 24; | ||
410 | seq[4] = pn64 >> 32; | ||
411 | seq[5] = pn64 >> 40; | ||
412 | } | ||
389 | params.seq = seq; | 413 | params.seq = seq; |
390 | params.seq_len = 6; | 414 | params.seq_len = 6; |
391 | break; | 415 | break; |
392 | case WLAN_CIPHER_SUITE_GCMP: | 416 | case WLAN_CIPHER_SUITE_GCMP: |
393 | case WLAN_CIPHER_SUITE_GCMP_256: | 417 | case WLAN_CIPHER_SUITE_GCMP_256: |
394 | pn64 = atomic64_read(&key->u.gcmp.tx_pn); | 418 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
395 | seq[0] = pn64; | 419 | !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
396 | seq[1] = pn64 >> 8; | 420 | drv_get_key_seq(sdata->local, key, &kseq); |
397 | seq[2] = pn64 >> 16; | 421 | memcpy(seq, kseq.gcmp.pn, 6); |
398 | seq[3] = pn64 >> 24; | 422 | } else { |
399 | seq[4] = pn64 >> 32; | 423 | pn64 = atomic64_read(&key->u.gcmp.tx_pn); |
400 | seq[5] = pn64 >> 40; | 424 | seq[0] = pn64; |
425 | seq[1] = pn64 >> 8; | ||
426 | seq[2] = pn64 >> 16; | ||
427 | seq[3] = pn64 >> 24; | ||
428 | seq[4] = pn64 >> 32; | ||
429 | seq[5] = pn64 >> 40; | ||
430 | } | ||
401 | params.seq = seq; | 431 | params.seq = seq; |
402 | params.seq_len = 6; | 432 | params.seq_len = 6; |
403 | break; | 433 | break; |
434 | default: | ||
435 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | ||
436 | break; | ||
437 | if (WARN_ON(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) | ||
438 | break; | ||
439 | drv_get_key_seq(sdata->local, key, &kseq); | ||
440 | params.seq = kseq.hw.seq; | ||
441 | params.seq_len = kseq.hw.seq_len; | ||
442 | break; | ||
404 | } | 443 | } |
405 | 444 | ||
406 | params.key = key->conf.key; | 445 | params.key = key->conf.key; |
@@ -2099,10 +2138,14 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
2099 | int err; | 2138 | int err; |
2100 | 2139 | ||
2101 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { | 2140 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { |
2141 | ieee80211_check_fast_xmit_all(local); | ||
2142 | |||
2102 | err = drv_set_frag_threshold(local, wiphy->frag_threshold); | 2143 | err = drv_set_frag_threshold(local, wiphy->frag_threshold); |
2103 | 2144 | ||
2104 | if (err) | 2145 | if (err) { |
2146 | ieee80211_check_fast_xmit_all(local); | ||
2105 | return err; | 2147 | return err; |
2148 | } | ||
2106 | } | 2149 | } |
2107 | 2150 | ||
2108 | if ((changed & WIPHY_PARAM_COVERAGE_CLASS) || | 2151 | if ((changed & WIPHY_PARAM_COVERAGE_CLASS) || |
@@ -3336,8 +3379,14 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3336 | break; | 3379 | break; |
3337 | case NL80211_IFTYPE_STATION: | 3380 | case NL80211_IFTYPE_STATION: |
3338 | case NL80211_IFTYPE_P2P_CLIENT: | 3381 | case NL80211_IFTYPE_P2P_CLIENT: |
3339 | if (!sdata->u.mgd.associated) | 3382 | sdata_lock(sdata); |
3383 | if (!sdata->u.mgd.associated || | ||
3384 | (params->offchan && params->wait && | ||
3385 | local->ops->remain_on_channel && | ||
3386 | memcmp(sdata->u.mgd.associated->bssid, | ||
3387 | mgmt->bssid, ETH_ALEN))) | ||
3340 | need_offchan = true; | 3388 | need_offchan = true; |
3389 | sdata_unlock(sdata); | ||
3341 | break; | 3390 | break; |
3342 | case NL80211_IFTYPE_P2P_DEVICE: | 3391 | case NL80211_IFTYPE_P2P_DEVICE: |
3343 | need_offchan = true; | 3392 | need_offchan = true; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 5bcd4e5589d3..7e9b62475400 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -664,6 +664,8 @@ out: | |||
664 | ieee80211_bss_info_change_notify(sdata, | 664 | ieee80211_bss_info_change_notify(sdata, |
665 | BSS_CHANGED_IDLE); | 665 | BSS_CHANGED_IDLE); |
666 | 666 | ||
667 | ieee80211_check_fast_xmit_iface(sdata); | ||
668 | |||
667 | return ret; | 669 | return ret; |
668 | } | 670 | } |
669 | 671 | ||
@@ -1030,6 +1032,8 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata) | |||
1030 | if (sdata->vif.type == NL80211_IFTYPE_AP) | 1032 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
1031 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, false); | 1033 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, false); |
1032 | 1034 | ||
1035 | ieee80211_check_fast_xmit_iface(sdata); | ||
1036 | |||
1033 | if (ieee80211_chanctx_refcount(local, old_ctx) == 0) | 1037 | if (ieee80211_chanctx_refcount(local, old_ctx) == 0) |
1034 | ieee80211_free_chanctx(local, old_ctx); | 1038 | ieee80211_free_chanctx(local, old_ctx); |
1035 | 1039 | ||
@@ -1376,6 +1380,8 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) | |||
1376 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, | 1380 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, |
1377 | false); | 1381 | false); |
1378 | 1382 | ||
1383 | ieee80211_check_fast_xmit_iface(sdata); | ||
1384 | |||
1379 | sdata->radar_required = sdata->reserved_radar_required; | 1385 | sdata->radar_required = sdata->reserved_radar_required; |
1380 | 1386 | ||
1381 | if (sdata->vif.bss_conf.chandef.width != | 1387 | if (sdata->vif.bss_conf.chandef.width != |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 23813ebb349c..b17206db49b4 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -219,8 +219,8 @@ static const struct file_operations stats_ ##name## _ops = { \ | |||
219 | .llseek = generic_file_llseek, \ | 219 | .llseek = generic_file_llseek, \ |
220 | }; | 220 | }; |
221 | 221 | ||
222 | #define DEBUGFS_STATS_ADD(name, field) \ | 222 | #define DEBUGFS_STATS_ADD(name) \ |
223 | debugfs_create_u32(#name, 0400, statsd, (u32 *) &field); | 223 | debugfs_create_u32(#name, 0400, statsd, &local->name); |
224 | #define DEBUGFS_DEVSTATS_ADD(name) \ | 224 | #define DEBUGFS_DEVSTATS_ADD(name) \ |
225 | debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops); | 225 | debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops); |
226 | 226 | ||
@@ -255,53 +255,31 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
255 | if (!statsd) | 255 | if (!statsd) |
256 | return; | 256 | return; |
257 | 257 | ||
258 | DEBUGFS_STATS_ADD(transmitted_fragment_count, | ||
259 | local->dot11TransmittedFragmentCount); | ||
260 | DEBUGFS_STATS_ADD(multicast_transmitted_frame_count, | ||
261 | local->dot11MulticastTransmittedFrameCount); | ||
262 | DEBUGFS_STATS_ADD(failed_count, local->dot11FailedCount); | ||
263 | DEBUGFS_STATS_ADD(retry_count, local->dot11RetryCount); | ||
264 | DEBUGFS_STATS_ADD(multiple_retry_count, | ||
265 | local->dot11MultipleRetryCount); | ||
266 | DEBUGFS_STATS_ADD(frame_duplicate_count, | ||
267 | local->dot11FrameDuplicateCount); | ||
268 | DEBUGFS_STATS_ADD(received_fragment_count, | ||
269 | local->dot11ReceivedFragmentCount); | ||
270 | DEBUGFS_STATS_ADD(multicast_received_frame_count, | ||
271 | local->dot11MulticastReceivedFrameCount); | ||
272 | DEBUGFS_STATS_ADD(transmitted_frame_count, | ||
273 | local->dot11TransmittedFrameCount); | ||
274 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 258 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
275 | DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop); | 259 | DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount); |
276 | DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued); | 260 | DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount); |
277 | DEBUGFS_STATS_ADD(tx_handlers_drop_fragment, | 261 | DEBUGFS_STATS_ADD(dot11FailedCount); |
278 | local->tx_handlers_drop_fragment); | 262 | DEBUGFS_STATS_ADD(dot11RetryCount); |
279 | DEBUGFS_STATS_ADD(tx_handlers_drop_wep, | 263 | DEBUGFS_STATS_ADD(dot11MultipleRetryCount); |
280 | local->tx_handlers_drop_wep); | 264 | DEBUGFS_STATS_ADD(dot11FrameDuplicateCount); |
281 | DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc, | 265 | DEBUGFS_STATS_ADD(dot11ReceivedFragmentCount); |
282 | local->tx_handlers_drop_not_assoc); | 266 | DEBUGFS_STATS_ADD(dot11MulticastReceivedFrameCount); |
283 | DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port, | 267 | DEBUGFS_STATS_ADD(dot11TransmittedFrameCount); |
284 | local->tx_handlers_drop_unauth_port); | 268 | DEBUGFS_STATS_ADD(tx_handlers_drop); |
285 | DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop); | 269 | DEBUGFS_STATS_ADD(tx_handlers_queued); |
286 | DEBUGFS_STATS_ADD(rx_handlers_queued, local->rx_handlers_queued); | 270 | DEBUGFS_STATS_ADD(tx_handlers_drop_wep); |
287 | DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc, | 271 | DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc); |
288 | local->rx_handlers_drop_nullfunc); | 272 | DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port); |
289 | DEBUGFS_STATS_ADD(rx_handlers_drop_defrag, | 273 | DEBUGFS_STATS_ADD(rx_handlers_drop); |
290 | local->rx_handlers_drop_defrag); | 274 | DEBUGFS_STATS_ADD(rx_handlers_queued); |
291 | DEBUGFS_STATS_ADD(rx_handlers_drop_short, | 275 | DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc); |
292 | local->rx_handlers_drop_short); | 276 | DEBUGFS_STATS_ADD(rx_handlers_drop_defrag); |
293 | DEBUGFS_STATS_ADD(tx_expand_skb_head, | 277 | DEBUGFS_STATS_ADD(rx_handlers_drop_short); |
294 | local->tx_expand_skb_head); | 278 | DEBUGFS_STATS_ADD(tx_expand_skb_head); |
295 | DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned, | 279 | DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned); |
296 | local->tx_expand_skb_head_cloned); | 280 | DEBUGFS_STATS_ADD(rx_expand_skb_head_defrag); |
297 | DEBUGFS_STATS_ADD(rx_expand_skb_head, | 281 | DEBUGFS_STATS_ADD(rx_handlers_fragments); |
298 | local->rx_expand_skb_head); | 282 | DEBUGFS_STATS_ADD(tx_status_drop); |
299 | DEBUGFS_STATS_ADD(rx_expand_skb_head2, | ||
300 | local->rx_expand_skb_head2); | ||
301 | DEBUGFS_STATS_ADD(rx_handlers_fragments, | ||
302 | local->rx_handlers_fragments); | ||
303 | DEBUGFS_STATS_ADD(tx_status_drop, | ||
304 | local->tx_status_drop); | ||
305 | #endif | 283 | #endif |
306 | DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount); | 284 | DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount); |
307 | DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount); | 285 | DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 252859e90e8a..06d52935036d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -29,8 +29,6 @@ static ssize_t sta_ ##name## _read(struct file *file, \ | |||
29 | format_string, sta->field); \ | 29 | format_string, sta->field); \ |
30 | } | 30 | } |
31 | #define STA_READ_D(name, field) STA_READ(name, field, "%d\n") | 31 | #define STA_READ_D(name, field) STA_READ(name, field, "%d\n") |
32 | #define STA_READ_U(name, field) STA_READ(name, field, "%u\n") | ||
33 | #define STA_READ_S(name, field) STA_READ(name, field, "%s\n") | ||
34 | 32 | ||
35 | #define STA_OPS(name) \ | 33 | #define STA_OPS(name) \ |
36 | static const struct file_operations sta_ ##name## _ops = { \ | 34 | static const struct file_operations sta_ ##name## _ops = { \ |
@@ -52,10 +50,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
52 | STA_OPS(name) | 50 | STA_OPS(name) |
53 | 51 | ||
54 | STA_FILE(aid, sta.aid, D); | 52 | STA_FILE(aid, sta.aid, D); |
55 | STA_FILE(dev, sdata->name, S); | ||
56 | STA_FILE(last_signal, last_signal, D); | ||
57 | STA_FILE(last_ack_signal, last_ack_signal, D); | 53 | STA_FILE(last_ack_signal, last_ack_signal, D); |
58 | STA_FILE(beacon_loss_count, beacon_loss_count, D); | ||
59 | 54 | ||
60 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 55 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
61 | size_t count, loff_t *ppos) | 56 | size_t count, loff_t *ppos) |
@@ -101,40 +96,6 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file, | |||
101 | } | 96 | } |
102 | STA_OPS(num_ps_buf_frames); | 97 | STA_OPS(num_ps_buf_frames); |
103 | 98 | ||
104 | static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf, | ||
105 | size_t count, loff_t *ppos) | ||
106 | { | ||
107 | struct sta_info *sta = file->private_data; | ||
108 | return mac80211_format_buffer(userbuf, count, ppos, "%d\n", | ||
109 | jiffies_to_msecs(jiffies - sta->last_rx)); | ||
110 | } | ||
111 | STA_OPS(inactive_ms); | ||
112 | |||
113 | |||
114 | static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf, | ||
115 | size_t count, loff_t *ppos) | ||
116 | { | ||
117 | struct sta_info *sta = file->private_data; | ||
118 | struct timespec uptime; | ||
119 | struct tm result; | ||
120 | long connected_time_secs; | ||
121 | char buf[100]; | ||
122 | int res; | ||
123 | ktime_get_ts(&uptime); | ||
124 | connected_time_secs = uptime.tv_sec - sta->last_connected; | ||
125 | time_to_tm(connected_time_secs, 0, &result); | ||
126 | result.tm_year -= 70; | ||
127 | result.tm_mday -= 1; | ||
128 | res = scnprintf(buf, sizeof(buf), | ||
129 | "years - %ld\nmonths - %d\ndays - %d\nclock - %d:%d:%d\n\n", | ||
130 | result.tm_year, result.tm_mon, result.tm_mday, | ||
131 | result.tm_hour, result.tm_min, result.tm_sec); | ||
132 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | ||
133 | } | ||
134 | STA_OPS(connected_time); | ||
135 | |||
136 | |||
137 | |||
138 | static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, | 99 | static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, |
139 | size_t count, loff_t *ppos) | 100 | size_t count, loff_t *ppos) |
140 | { | 101 | { |
@@ -359,37 +320,6 @@ static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, | |||
359 | } | 320 | } |
360 | STA_OPS(vht_capa); | 321 | STA_OPS(vht_capa); |
361 | 322 | ||
362 | static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, | ||
363 | size_t count, loff_t *ppos) | ||
364 | { | ||
365 | struct sta_info *sta = file->private_data; | ||
366 | struct rate_info rinfo; | ||
367 | u16 rate; | ||
368 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo); | ||
369 | rate = cfg80211_calculate_bitrate(&rinfo); | ||
370 | |||
371 | return mac80211_format_buffer(userbuf, count, ppos, | ||
372 | "%d.%d MBit/s\n", | ||
373 | rate/10, rate%10); | ||
374 | } | ||
375 | STA_OPS(current_tx_rate); | ||
376 | |||
377 | static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf, | ||
378 | size_t count, loff_t *ppos) | ||
379 | { | ||
380 | struct sta_info *sta = file->private_data; | ||
381 | struct rate_info rinfo; | ||
382 | u16 rate; | ||
383 | |||
384 | sta_set_rate_info_rx(sta, &rinfo); | ||
385 | |||
386 | rate = cfg80211_calculate_bitrate(&rinfo); | ||
387 | |||
388 | return mac80211_format_buffer(userbuf, count, ppos, | ||
389 | "%d.%d MBit/s\n", | ||
390 | rate/10, rate%10); | ||
391 | } | ||
392 | STA_OPS(last_rx_rate); | ||
393 | 323 | ||
394 | #define DEBUGFS_ADD(name) \ | 324 | #define DEBUGFS_ADD(name) \ |
395 | debugfs_create_file(#name, 0400, \ | 325 | debugfs_create_file(#name, 0400, \ |
@@ -432,30 +362,15 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
432 | 362 | ||
433 | DEBUGFS_ADD(flags); | 363 | DEBUGFS_ADD(flags); |
434 | DEBUGFS_ADD(num_ps_buf_frames); | 364 | DEBUGFS_ADD(num_ps_buf_frames); |
435 | DEBUGFS_ADD(inactive_ms); | ||
436 | DEBUGFS_ADD(connected_time); | ||
437 | DEBUGFS_ADD(last_seq_ctrl); | 365 | DEBUGFS_ADD(last_seq_ctrl); |
438 | DEBUGFS_ADD(agg_status); | 366 | DEBUGFS_ADD(agg_status); |
439 | DEBUGFS_ADD(dev); | ||
440 | DEBUGFS_ADD(last_signal); | ||
441 | DEBUGFS_ADD(beacon_loss_count); | ||
442 | DEBUGFS_ADD(ht_capa); | 367 | DEBUGFS_ADD(ht_capa); |
443 | DEBUGFS_ADD(vht_capa); | 368 | DEBUGFS_ADD(vht_capa); |
444 | DEBUGFS_ADD(last_ack_signal); | 369 | DEBUGFS_ADD(last_ack_signal); |
445 | DEBUGFS_ADD(current_tx_rate); | ||
446 | DEBUGFS_ADD(last_rx_rate); | ||
447 | 370 | ||
448 | DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); | ||
449 | DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); | ||
450 | DEBUGFS_ADD_COUNTER(rx_bytes, rx_bytes); | ||
451 | DEBUGFS_ADD_COUNTER(tx_bytes, tx_bytes); | ||
452 | DEBUGFS_ADD_COUNTER(rx_duplicates, num_duplicates); | 371 | DEBUGFS_ADD_COUNTER(rx_duplicates, num_duplicates); |
453 | DEBUGFS_ADD_COUNTER(rx_fragments, rx_fragments); | 372 | DEBUGFS_ADD_COUNTER(rx_fragments, rx_fragments); |
454 | DEBUGFS_ADD_COUNTER(rx_dropped, rx_dropped); | ||
455 | DEBUGFS_ADD_COUNTER(tx_fragments, tx_fragments); | ||
456 | DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count); | 373 | DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count); |
457 | DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed); | ||
458 | DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); | ||
459 | 374 | ||
460 | if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) | 375 | if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) |
461 | debugfs_create_x32("driver_buffered_tids", 0400, | 376 | debugfs_create_x32("driver_buffered_tids", 0400, |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 26e1ca8a474a..c01e681b90fb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -417,12 +417,13 @@ static inline int drv_get_stats(struct ieee80211_local *local, | |||
417 | return ret; | 417 | return ret; |
418 | } | 418 | } |
419 | 419 | ||
420 | static inline void drv_get_tkip_seq(struct ieee80211_local *local, | 420 | static inline void drv_get_key_seq(struct ieee80211_local *local, |
421 | u8 hw_key_idx, u32 *iv32, u16 *iv16) | 421 | struct ieee80211_key *key, |
422 | struct ieee80211_key_seq *seq) | ||
422 | { | 423 | { |
423 | if (local->ops->get_tkip_seq) | 424 | if (local->ops->get_key_seq) |
424 | local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); | 425 | local->ops->get_key_seq(&local->hw, &key->conf, seq); |
425 | trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); | 426 | trace_drv_get_key_seq(local, &key->conf); |
426 | } | 427 | } |
427 | 428 | ||
428 | static inline int drv_set_frag_threshold(struct ieee80211_local *local, | 429 | static inline int drv_set_frag_threshold(struct ieee80211_local *local, |
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c index 52bcea6ad9e8..188faab11c24 100644 --- a/net/mac80211/ethtool.c +++ b/net/mac80211/ethtool.c | |||
@@ -38,7 +38,7 @@ static void ieee80211_get_ringparam(struct net_device *dev, | |||
38 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | 38 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { |
39 | "rx_packets", "rx_bytes", | 39 | "rx_packets", "rx_bytes", |
40 | "rx_duplicates", "rx_fragments", "rx_dropped", | 40 | "rx_duplicates", "rx_fragments", "rx_dropped", |
41 | "tx_packets", "tx_bytes", "tx_fragments", | 41 | "tx_packets", "tx_bytes", |
42 | "tx_filtered", "tx_retry_failed", "tx_retries", | 42 | "tx_filtered", "tx_retry_failed", "tx_retries", |
43 | "beacon_loss", "sta_state", "txrate", "rxrate", "signal", | 43 | "beacon_loss", "sta_state", "txrate", "rxrate", "signal", |
44 | "channel", "noise", "ch_time", "ch_time_busy", | 44 | "channel", "noise", "ch_time", "ch_time_busy", |
@@ -87,7 +87,6 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
87 | \ | 87 | \ |
88 | data[i++] += sinfo.tx_packets; \ | 88 | data[i++] += sinfo.tx_packets; \ |
89 | data[i++] += sinfo.tx_bytes; \ | 89 | data[i++] += sinfo.tx_bytes; \ |
90 | data[i++] += sta->tx_fragments; \ | ||
91 | data[i++] += sta->tx_filtered_count; \ | 90 | data[i++] += sta->tx_filtered_count; \ |
92 | data[i++] += sta->tx_retry_failed; \ | 91 | data[i++] += sta->tx_retry_failed; \ |
93 | data[i++] += sta->tx_retry_count; \ | 92 | data[i++] += sta->tx_retry_count; \ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ab46ab4a7249..241b74f3bd81 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -181,8 +181,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
181 | 181 | ||
182 | /** | 182 | /** |
183 | * enum ieee80211_packet_rx_flags - packet RX flags | 183 | * enum ieee80211_packet_rx_flags - packet RX flags |
184 | * @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed | ||
185 | * (incl. multicast frames) | ||
186 | * @IEEE80211_RX_FRAGMENTED: fragmented frame | 184 | * @IEEE80211_RX_FRAGMENTED: fragmented frame |
187 | * @IEEE80211_RX_AMSDU: a-MSDU packet | 185 | * @IEEE80211_RX_AMSDU: a-MSDU packet |
188 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed | 186 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed |
@@ -192,7 +190,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
192 | * @rx_flags field of &struct ieee80211_rx_status. | 190 | * @rx_flags field of &struct ieee80211_rx_status. |
193 | */ | 191 | */ |
194 | enum ieee80211_packet_rx_flags { | 192 | enum ieee80211_packet_rx_flags { |
195 | IEEE80211_RX_RA_MATCH = BIT(1), | ||
196 | IEEE80211_RX_FRAGMENTED = BIT(2), | 193 | IEEE80211_RX_FRAGMENTED = BIT(2), |
197 | IEEE80211_RX_AMSDU = BIT(3), | 194 | IEEE80211_RX_AMSDU = BIT(3), |
198 | IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4), | 195 | IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4), |
@@ -725,7 +722,6 @@ struct ieee80211_if_mesh { | |||
725 | * enum ieee80211_sub_if_data_flags - virtual interface flags | 722 | * enum ieee80211_sub_if_data_flags - virtual interface flags |
726 | * | 723 | * |
727 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets | 724 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets |
728 | * @IEEE80211_SDATA_PROMISC: interface is promisc | ||
729 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode | 725 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode |
730 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | 726 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between |
731 | * associated stations and deliver multicast frames both | 727 | * associated stations and deliver multicast frames both |
@@ -735,7 +731,6 @@ struct ieee80211_if_mesh { | |||
735 | */ | 731 | */ |
736 | enum ieee80211_sub_if_data_flags { | 732 | enum ieee80211_sub_if_data_flags { |
737 | IEEE80211_SDATA_ALLMULTI = BIT(0), | 733 | IEEE80211_SDATA_ALLMULTI = BIT(0), |
738 | IEEE80211_SDATA_PROMISC = BIT(1), | ||
739 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), | 734 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), |
740 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), | 735 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), |
741 | IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), | 736 | IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), |
@@ -1211,8 +1206,8 @@ struct ieee80211_local { | |||
1211 | 1206 | ||
1212 | atomic_t agg_queue_stop[IEEE80211_MAX_QUEUES]; | 1207 | atomic_t agg_queue_stop[IEEE80211_MAX_QUEUES]; |
1213 | 1208 | ||
1214 | /* number of interfaces with corresponding IFF_ flags */ | 1209 | /* number of interfaces with allmulti RX */ |
1215 | atomic_t iff_allmultis, iff_promiscs; | 1210 | atomic_t iff_allmultis; |
1216 | 1211 | ||
1217 | struct rate_control_ref *rate_ctrl; | 1212 | struct rate_control_ref *rate_ctrl; |
1218 | 1213 | ||
@@ -1264,6 +1259,15 @@ struct ieee80211_local { | |||
1264 | struct list_head chanctx_list; | 1259 | struct list_head chanctx_list; |
1265 | struct mutex chanctx_mtx; | 1260 | struct mutex chanctx_mtx; |
1266 | 1261 | ||
1262 | #ifdef CONFIG_MAC80211_LEDS | ||
1263 | struct led_trigger tx_led, rx_led, assoc_led, radio_led; | ||
1264 | struct led_trigger tpt_led; | ||
1265 | atomic_t tx_led_active, rx_led_active, assoc_led_active; | ||
1266 | atomic_t radio_led_active, tpt_led_active; | ||
1267 | struct tpt_led_trigger *tpt_led_trigger; | ||
1268 | #endif | ||
1269 | |||
1270 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
1267 | /* SNMP counters */ | 1271 | /* SNMP counters */ |
1268 | /* dot11CountersTable */ | 1272 | /* dot11CountersTable */ |
1269 | u32 dot11TransmittedFragmentCount; | 1273 | u32 dot11TransmittedFragmentCount; |
@@ -1276,18 +1280,9 @@ struct ieee80211_local { | |||
1276 | u32 dot11MulticastReceivedFrameCount; | 1280 | u32 dot11MulticastReceivedFrameCount; |
1277 | u32 dot11TransmittedFrameCount; | 1281 | u32 dot11TransmittedFrameCount; |
1278 | 1282 | ||
1279 | #ifdef CONFIG_MAC80211_LEDS | ||
1280 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; | ||
1281 | struct tpt_led_trigger *tpt_led_trigger; | ||
1282 | char tx_led_name[32], rx_led_name[32], | ||
1283 | assoc_led_name[32], radio_led_name[32]; | ||
1284 | #endif | ||
1285 | |||
1286 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
1287 | /* TX/RX handler statistics */ | 1283 | /* TX/RX handler statistics */ |
1288 | unsigned int tx_handlers_drop; | 1284 | unsigned int tx_handlers_drop; |
1289 | unsigned int tx_handlers_queued; | 1285 | unsigned int tx_handlers_queued; |
1290 | unsigned int tx_handlers_drop_fragment; | ||
1291 | unsigned int tx_handlers_drop_wep; | 1286 | unsigned int tx_handlers_drop_wep; |
1292 | unsigned int tx_handlers_drop_not_assoc; | 1287 | unsigned int tx_handlers_drop_not_assoc; |
1293 | unsigned int tx_handlers_drop_unauth_port; | 1288 | unsigned int tx_handlers_drop_unauth_port; |
@@ -1298,8 +1293,7 @@ struct ieee80211_local { | |||
1298 | unsigned int rx_handlers_drop_short; | 1293 | unsigned int rx_handlers_drop_short; |
1299 | unsigned int tx_expand_skb_head; | 1294 | unsigned int tx_expand_skb_head; |
1300 | unsigned int tx_expand_skb_head_cloned; | 1295 | unsigned int tx_expand_skb_head_cloned; |
1301 | unsigned int rx_expand_skb_head; | 1296 | unsigned int rx_expand_skb_head_defrag; |
1302 | unsigned int rx_expand_skb_head2; | ||
1303 | unsigned int rx_handlers_fragments; | 1297 | unsigned int rx_handlers_fragments; |
1304 | unsigned int tx_status_drop; | 1298 | unsigned int tx_status_drop; |
1305 | #define I802_DEBUG_INC(c) (c)++ | 1299 | #define I802_DEBUG_INC(c) (c)++ |
@@ -1651,6 +1645,11 @@ struct sk_buff * | |||
1651 | ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, | 1645 | ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, |
1652 | struct sk_buff *skb, u32 info_flags); | 1646 | struct sk_buff *skb, u32 info_flags); |
1653 | 1647 | ||
1648 | void ieee80211_check_fast_xmit(struct sta_info *sta); | ||
1649 | void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); | ||
1650 | void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata); | ||
1651 | void ieee80211_clear_fast_xmit(struct sta_info *sta); | ||
1652 | |||
1654 | /* HT */ | 1653 | /* HT */ |
1655 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | 1654 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, |
1656 | struct ieee80211_sta_ht_cap *ht_cap); | 1655 | struct ieee80211_sta_ht_cap *ht_cap); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b4ac596a7cb7..dc2d7133c4f6 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -697,9 +697,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
697 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 697 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
698 | atomic_inc(&local->iff_allmultis); | 698 | atomic_inc(&local->iff_allmultis); |
699 | 699 | ||
700 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
701 | atomic_inc(&local->iff_promiscs); | ||
702 | |||
703 | if (coming_up) | 700 | if (coming_up) |
704 | local->open_count++; | 701 | local->open_count++; |
705 | 702 | ||
@@ -827,13 +824,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
827 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 824 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
828 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 825 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
829 | 826 | ||
830 | /* don't count this interface for promisc/allmulti while it is down */ | 827 | /* don't count this interface for allmulti while it is down */ |
831 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 828 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
832 | atomic_dec(&local->iff_allmultis); | 829 | atomic_dec(&local->iff_allmultis); |
833 | 830 | ||
834 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
835 | atomic_dec(&local->iff_promiscs); | ||
836 | |||
837 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 831 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
838 | local->fif_pspoll--; | 832 | local->fif_pspoll--; |
839 | local->fif_probe_req--; | 833 | local->fif_probe_req--; |
@@ -1047,12 +1041,10 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
1047 | { | 1041 | { |
1048 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1042 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1049 | struct ieee80211_local *local = sdata->local; | 1043 | struct ieee80211_local *local = sdata->local; |
1050 | int allmulti, promisc, sdata_allmulti, sdata_promisc; | 1044 | int allmulti, sdata_allmulti; |
1051 | 1045 | ||
1052 | allmulti = !!(dev->flags & IFF_ALLMULTI); | 1046 | allmulti = !!(dev->flags & IFF_ALLMULTI); |
1053 | promisc = !!(dev->flags & IFF_PROMISC); | ||
1054 | sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); | 1047 | sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); |
1055 | sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); | ||
1056 | 1048 | ||
1057 | if (allmulti != sdata_allmulti) { | 1049 | if (allmulti != sdata_allmulti) { |
1058 | if (dev->flags & IFF_ALLMULTI) | 1050 | if (dev->flags & IFF_ALLMULTI) |
@@ -1062,13 +1054,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
1062 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | 1054 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; |
1063 | } | 1055 | } |
1064 | 1056 | ||
1065 | if (promisc != sdata_promisc) { | ||
1066 | if (dev->flags & IFF_PROMISC) | ||
1067 | atomic_inc(&local->iff_promiscs); | ||
1068 | else | ||
1069 | atomic_dec(&local->iff_promiscs); | ||
1070 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | ||
1071 | } | ||
1072 | spin_lock_bh(&local->filter_lock); | 1057 | spin_lock_bh(&local->filter_lock); |
1073 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 1058 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
1074 | spin_unlock_bh(&local->filter_lock); | 1059 | spin_unlock_bh(&local->filter_lock); |
@@ -1109,6 +1094,35 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev, | |||
1109 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); | 1094 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); |
1110 | } | 1095 | } |
1111 | 1096 | ||
1097 | static struct rtnl_link_stats64 * | ||
1098 | ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) | ||
1099 | { | ||
1100 | int i; | ||
1101 | |||
1102 | for_each_possible_cpu(i) { | ||
1103 | const struct pcpu_sw_netstats *tstats; | ||
1104 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
1105 | unsigned int start; | ||
1106 | |||
1107 | tstats = per_cpu_ptr(dev->tstats, i); | ||
1108 | |||
1109 | do { | ||
1110 | start = u64_stats_fetch_begin_irq(&tstats->syncp); | ||
1111 | rx_packets = tstats->rx_packets; | ||
1112 | tx_packets = tstats->tx_packets; | ||
1113 | rx_bytes = tstats->rx_bytes; | ||
1114 | tx_bytes = tstats->tx_bytes; | ||
1115 | } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); | ||
1116 | |||
1117 | stats->rx_packets += rx_packets; | ||
1118 | stats->tx_packets += tx_packets; | ||
1119 | stats->rx_bytes += rx_bytes; | ||
1120 | stats->tx_bytes += tx_bytes; | ||
1121 | } | ||
1122 | |||
1123 | return stats; | ||
1124 | } | ||
1125 | |||
1112 | static const struct net_device_ops ieee80211_dataif_ops = { | 1126 | static const struct net_device_ops ieee80211_dataif_ops = { |
1113 | .ndo_open = ieee80211_open, | 1127 | .ndo_open = ieee80211_open, |
1114 | .ndo_stop = ieee80211_stop, | 1128 | .ndo_stop = ieee80211_stop, |
@@ -1118,6 +1132,7 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
1118 | .ndo_change_mtu = ieee80211_change_mtu, | 1132 | .ndo_change_mtu = ieee80211_change_mtu, |
1119 | .ndo_set_mac_address = ieee80211_change_mac, | 1133 | .ndo_set_mac_address = ieee80211_change_mac, |
1120 | .ndo_select_queue = ieee80211_netdev_select_queue, | 1134 | .ndo_select_queue = ieee80211_netdev_select_queue, |
1135 | .ndo_get_stats64 = ieee80211_get_stats64, | ||
1121 | }; | 1136 | }; |
1122 | 1137 | ||
1123 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, | 1138 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, |
@@ -1151,14 +1166,21 @@ static const struct net_device_ops ieee80211_monitorif_ops = { | |||
1151 | .ndo_change_mtu = ieee80211_change_mtu, | 1166 | .ndo_change_mtu = ieee80211_change_mtu, |
1152 | .ndo_set_mac_address = ieee80211_change_mac, | 1167 | .ndo_set_mac_address = ieee80211_change_mac, |
1153 | .ndo_select_queue = ieee80211_monitor_select_queue, | 1168 | .ndo_select_queue = ieee80211_monitor_select_queue, |
1169 | .ndo_get_stats64 = ieee80211_get_stats64, | ||
1154 | }; | 1170 | }; |
1155 | 1171 | ||
1172 | static void ieee80211_if_free(struct net_device *dev) | ||
1173 | { | ||
1174 | free_percpu(dev->tstats); | ||
1175 | free_netdev(dev); | ||
1176 | } | ||
1177 | |||
1156 | static void ieee80211_if_setup(struct net_device *dev) | 1178 | static void ieee80211_if_setup(struct net_device *dev) |
1157 | { | 1179 | { |
1158 | ether_setup(dev); | 1180 | ether_setup(dev); |
1159 | dev->priv_flags &= ~IFF_TX_SKB_SHARING; | 1181 | dev->priv_flags &= ~IFF_TX_SKB_SHARING; |
1160 | dev->netdev_ops = &ieee80211_dataif_ops; | 1182 | dev->netdev_ops = &ieee80211_dataif_ops; |
1161 | dev->destructor = free_netdev; | 1183 | dev->destructor = ieee80211_if_free; |
1162 | } | 1184 | } |
1163 | 1185 | ||
1164 | static void ieee80211_iface_work(struct work_struct *work) | 1186 | static void ieee80211_iface_work(struct work_struct *work) |
@@ -1699,6 +1721,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1699 | return -ENOMEM; | 1721 | return -ENOMEM; |
1700 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1722 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
1701 | 1723 | ||
1724 | ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | ||
1725 | if (!ndev->tstats) { | ||
1726 | free_netdev(ndev); | ||
1727 | return -ENOMEM; | ||
1728 | } | ||
1729 | |||
1702 | ndev->needed_headroom = local->tx_headroom + | 1730 | ndev->needed_headroom = local->tx_headroom + |
1703 | 4*6 /* four MAC addresses */ | 1731 | 4*6 /* four MAC addresses */ |
1704 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | 1732 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 2291cd730091..2e677376c958 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -229,6 +229,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | |||
229 | 229 | ||
230 | if (uni) { | 230 | if (uni) { |
231 | rcu_assign_pointer(sdata->default_unicast_key, key); | 231 | rcu_assign_pointer(sdata->default_unicast_key, key); |
232 | ieee80211_check_fast_xmit_iface(sdata); | ||
232 | drv_set_default_unicast_key(sdata->local, sdata, idx); | 233 | drv_set_default_unicast_key(sdata->local, sdata, idx); |
233 | } | 234 | } |
234 | 235 | ||
@@ -298,6 +299,7 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
298 | if (pairwise) { | 299 | if (pairwise) { |
299 | rcu_assign_pointer(sta->ptk[idx], new); | 300 | rcu_assign_pointer(sta->ptk[idx], new); |
300 | sta->ptk_idx = idx; | 301 | sta->ptk_idx = idx; |
302 | ieee80211_check_fast_xmit(sta); | ||
301 | } else { | 303 | } else { |
302 | rcu_assign_pointer(sta->gtk[idx], new); | 304 | rcu_assign_pointer(sta->gtk[idx], new); |
303 | sta->gtk_idx = idx; | 305 | sta->gtk_idx = idx; |
@@ -483,15 +485,17 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
483 | break; | 485 | break; |
484 | default: | 486 | default: |
485 | if (cs) { | 487 | if (cs) { |
486 | size_t len = (seq_len > MAX_PN_LEN) ? | 488 | if (seq_len && seq_len != cs->pn_len) { |
487 | MAX_PN_LEN : seq_len; | 489 | kfree(key); |
490 | return ERR_PTR(-EINVAL); | ||
491 | } | ||
488 | 492 | ||
489 | key->conf.iv_len = cs->hdr_len; | 493 | key->conf.iv_len = cs->hdr_len; |
490 | key->conf.icv_len = cs->mic_len; | 494 | key->conf.icv_len = cs->mic_len; |
491 | for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) | 495 | for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) |
492 | for (j = 0; j < len; j++) | 496 | for (j = 0; j < seq_len; j++) |
493 | key->u.gen.rx_pn[i][j] = | 497 | key->u.gen.rx_pn[i][j] = |
494 | seq[len - j - 1]; | 498 | seq[seq_len - j - 1]; |
495 | key->flags |= KEY_FLAG_CIPHER_SCHEME; | 499 | key->flags |= KEY_FLAG_CIPHER_SCHEME; |
496 | } | 500 | } |
497 | } | 501 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index c5a31835be0e..df430a618764 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -18,7 +18,6 @@ | |||
18 | 18 | ||
19 | #define NUM_DEFAULT_KEYS 4 | 19 | #define NUM_DEFAULT_KEYS 4 |
20 | #define NUM_DEFAULT_MGMT_KEYS 2 | 20 | #define NUM_DEFAULT_MGMT_KEYS 2 |
21 | #define MAX_PN_LEN 16 | ||
22 | 21 | ||
23 | struct ieee80211_local; | 22 | struct ieee80211_local; |
24 | struct ieee80211_sub_if_data; | 23 | struct ieee80211_sub_if_data; |
@@ -116,7 +115,7 @@ struct ieee80211_key { | |||
116 | } gcmp; | 115 | } gcmp; |
117 | struct { | 116 | struct { |
118 | /* generic cipher scheme */ | 117 | /* generic cipher scheme */ |
119 | u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN]; | 118 | u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_MAX_PN_LEN]; |
120 | } gen; | 119 | } gen; |
121 | } u; | 120 | } u; |
122 | 121 | ||
diff --git a/net/mac80211/led.c b/net/mac80211/led.c index e2b836446af3..38f05565eaac 100644 --- a/net/mac80211/led.c +++ b/net/mac80211/led.c | |||
@@ -12,96 +12,175 @@ | |||
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include "led.h" | 13 | #include "led.h" |
14 | 14 | ||
15 | #define MAC80211_BLINK_DELAY 50 /* ms */ | ||
16 | |||
17 | void ieee80211_led_rx(struct ieee80211_local *local) | ||
18 | { | ||
19 | unsigned long led_delay = MAC80211_BLINK_DELAY; | ||
20 | if (unlikely(!local->rx_led)) | ||
21 | return; | ||
22 | led_trigger_blink_oneshot(local->rx_led, &led_delay, &led_delay, 0); | ||
23 | } | ||
24 | |||
25 | void ieee80211_led_tx(struct ieee80211_local *local) | ||
26 | { | ||
27 | unsigned long led_delay = MAC80211_BLINK_DELAY; | ||
28 | if (unlikely(!local->tx_led)) | ||
29 | return; | ||
30 | led_trigger_blink_oneshot(local->tx_led, &led_delay, &led_delay, 0); | ||
31 | } | ||
32 | |||
33 | void ieee80211_led_assoc(struct ieee80211_local *local, bool associated) | 15 | void ieee80211_led_assoc(struct ieee80211_local *local, bool associated) |
34 | { | 16 | { |
35 | if (unlikely(!local->assoc_led)) | 17 | if (!atomic_read(&local->assoc_led_active)) |
36 | return; | 18 | return; |
37 | if (associated) | 19 | if (associated) |
38 | led_trigger_event(local->assoc_led, LED_FULL); | 20 | led_trigger_event(&local->assoc_led, LED_FULL); |
39 | else | 21 | else |
40 | led_trigger_event(local->assoc_led, LED_OFF); | 22 | led_trigger_event(&local->assoc_led, LED_OFF); |
41 | } | 23 | } |
42 | 24 | ||
43 | void ieee80211_led_radio(struct ieee80211_local *local, bool enabled) | 25 | void ieee80211_led_radio(struct ieee80211_local *local, bool enabled) |
44 | { | 26 | { |
45 | if (unlikely(!local->radio_led)) | 27 | if (!atomic_read(&local->radio_led_active)) |
46 | return; | 28 | return; |
47 | if (enabled) | 29 | if (enabled) |
48 | led_trigger_event(local->radio_led, LED_FULL); | 30 | led_trigger_event(&local->radio_led, LED_FULL); |
49 | else | 31 | else |
50 | led_trigger_event(local->radio_led, LED_OFF); | 32 | led_trigger_event(&local->radio_led, LED_OFF); |
33 | } | ||
34 | |||
35 | void ieee80211_alloc_led_names(struct ieee80211_local *local) | ||
36 | { | ||
37 | local->rx_led.name = kasprintf(GFP_KERNEL, "%srx", | ||
38 | wiphy_name(local->hw.wiphy)); | ||
39 | local->tx_led.name = kasprintf(GFP_KERNEL, "%stx", | ||
40 | wiphy_name(local->hw.wiphy)); | ||
41 | local->assoc_led.name = kasprintf(GFP_KERNEL, "%sassoc", | ||
42 | wiphy_name(local->hw.wiphy)); | ||
43 | local->radio_led.name = kasprintf(GFP_KERNEL, "%sradio", | ||
44 | wiphy_name(local->hw.wiphy)); | ||
45 | } | ||
46 | |||
47 | void ieee80211_free_led_names(struct ieee80211_local *local) | ||
48 | { | ||
49 | kfree(local->rx_led.name); | ||
50 | kfree(local->tx_led.name); | ||
51 | kfree(local->assoc_led.name); | ||
52 | kfree(local->radio_led.name); | ||
53 | } | ||
54 | |||
55 | static void ieee80211_tx_led_activate(struct led_classdev *led_cdev) | ||
56 | { | ||
57 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
58 | struct ieee80211_local, | ||
59 | tx_led); | ||
60 | |||
61 | atomic_inc(&local->tx_led_active); | ||
62 | } | ||
63 | |||
64 | static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev) | ||
65 | { | ||
66 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
67 | struct ieee80211_local, | ||
68 | tx_led); | ||
69 | |||
70 | atomic_dec(&local->tx_led_active); | ||
71 | } | ||
72 | |||
73 | static void ieee80211_rx_led_activate(struct led_classdev *led_cdev) | ||
74 | { | ||
75 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
76 | struct ieee80211_local, | ||
77 | rx_led); | ||
78 | |||
79 | atomic_inc(&local->rx_led_active); | ||
80 | } | ||
81 | |||
82 | static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev) | ||
83 | { | ||
84 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
85 | struct ieee80211_local, | ||
86 | rx_led); | ||
87 | |||
88 | atomic_dec(&local->rx_led_active); | ||
89 | } | ||
90 | |||
91 | static void ieee80211_assoc_led_activate(struct led_classdev *led_cdev) | ||
92 | { | ||
93 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
94 | struct ieee80211_local, | ||
95 | assoc_led); | ||
96 | |||
97 | atomic_inc(&local->assoc_led_active); | ||
98 | } | ||
99 | |||
100 | static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev) | ||
101 | { | ||
102 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
103 | struct ieee80211_local, | ||
104 | assoc_led); | ||
105 | |||
106 | atomic_dec(&local->assoc_led_active); | ||
107 | } | ||
108 | |||
109 | static void ieee80211_radio_led_activate(struct led_classdev *led_cdev) | ||
110 | { | ||
111 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
112 | struct ieee80211_local, | ||
113 | radio_led); | ||
114 | |||
115 | atomic_inc(&local->radio_led_active); | ||
116 | } | ||
117 | |||
118 | static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev) | ||
119 | { | ||
120 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
121 | struct ieee80211_local, | ||
122 | radio_led); | ||
123 | |||
124 | atomic_dec(&local->radio_led_active); | ||
125 | } | ||
126 | |||
127 | static void ieee80211_tpt_led_activate(struct led_classdev *led_cdev) | ||
128 | { | ||
129 | struct ieee80211_local *local = container_of(led_cdev->trigger, | ||
130 | struct ieee80211_local, | ||
131 | tpt_led); | ||
132 | |||
133 | atomic_inc(&local->tpt_led_active); | ||
51 | } | 134 | } |
52 | 135 | ||
53 | void ieee80211_led_names(struct ieee80211_local *local) | 136 | static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev) |
54 | { | 137 | { |
55 | snprintf(local->rx_led_name, sizeof(local->rx_led_name), | 138 | struct ieee80211_local *local = container_of(led_cdev->trigger, |
56 | "%srx", wiphy_name(local->hw.wiphy)); | 139 | struct ieee80211_local, |
57 | snprintf(local->tx_led_name, sizeof(local->tx_led_name), | 140 | tpt_led); |
58 | "%stx", wiphy_name(local->hw.wiphy)); | 141 | |
59 | snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), | 142 | atomic_dec(&local->tpt_led_active); |
60 | "%sassoc", wiphy_name(local->hw.wiphy)); | ||
61 | snprintf(local->radio_led_name, sizeof(local->radio_led_name), | ||
62 | "%sradio", wiphy_name(local->hw.wiphy)); | ||
63 | } | 143 | } |
64 | 144 | ||
65 | void ieee80211_led_init(struct ieee80211_local *local) | 145 | void ieee80211_led_init(struct ieee80211_local *local) |
66 | { | 146 | { |
67 | local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 147 | atomic_set(&local->rx_led_active, 0); |
68 | if (local->rx_led) { | 148 | local->rx_led.activate = ieee80211_rx_led_activate; |
69 | local->rx_led->name = local->rx_led_name; | 149 | local->rx_led.deactivate = ieee80211_rx_led_deactivate; |
70 | if (led_trigger_register(local->rx_led)) { | 150 | if (local->rx_led.name && led_trigger_register(&local->rx_led)) { |
71 | kfree(local->rx_led); | 151 | kfree(local->rx_led.name); |
72 | local->rx_led = NULL; | 152 | local->rx_led.name = NULL; |
73 | } | ||
74 | } | 153 | } |
75 | 154 | ||
76 | local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 155 | atomic_set(&local->tx_led_active, 0); |
77 | if (local->tx_led) { | 156 | local->tx_led.activate = ieee80211_tx_led_activate; |
78 | local->tx_led->name = local->tx_led_name; | 157 | local->tx_led.deactivate = ieee80211_tx_led_deactivate; |
79 | if (led_trigger_register(local->tx_led)) { | 158 | if (local->tx_led.name && led_trigger_register(&local->tx_led)) { |
80 | kfree(local->tx_led); | 159 | kfree(local->tx_led.name); |
81 | local->tx_led = NULL; | 160 | local->tx_led.name = NULL; |
82 | } | ||
83 | } | 161 | } |
84 | 162 | ||
85 | local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 163 | atomic_set(&local->assoc_led_active, 0); |
86 | if (local->assoc_led) { | 164 | local->assoc_led.activate = ieee80211_assoc_led_activate; |
87 | local->assoc_led->name = local->assoc_led_name; | 165 | local->assoc_led.deactivate = ieee80211_assoc_led_deactivate; |
88 | if (led_trigger_register(local->assoc_led)) { | 166 | if (local->assoc_led.name && led_trigger_register(&local->assoc_led)) { |
89 | kfree(local->assoc_led); | 167 | kfree(local->assoc_led.name); |
90 | local->assoc_led = NULL; | 168 | local->assoc_led.name = NULL; |
91 | } | ||
92 | } | 169 | } |
93 | 170 | ||
94 | local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 171 | atomic_set(&local->radio_led_active, 0); |
95 | if (local->radio_led) { | 172 | local->radio_led.activate = ieee80211_radio_led_activate; |
96 | local->radio_led->name = local->radio_led_name; | 173 | local->radio_led.deactivate = ieee80211_radio_led_deactivate; |
97 | if (led_trigger_register(local->radio_led)) { | 174 | if (local->radio_led.name && led_trigger_register(&local->radio_led)) { |
98 | kfree(local->radio_led); | 175 | kfree(local->radio_led.name); |
99 | local->radio_led = NULL; | 176 | local->radio_led.name = NULL; |
100 | } | ||
101 | } | 177 | } |
102 | 178 | ||
179 | atomic_set(&local->tpt_led_active, 0); | ||
103 | if (local->tpt_led_trigger) { | 180 | if (local->tpt_led_trigger) { |
104 | if (led_trigger_register(&local->tpt_led_trigger->trig)) { | 181 | local->tpt_led.activate = ieee80211_tpt_led_activate; |
182 | local->tpt_led.deactivate = ieee80211_tpt_led_deactivate; | ||
183 | if (led_trigger_register(&local->tpt_led)) { | ||
105 | kfree(local->tpt_led_trigger); | 184 | kfree(local->tpt_led_trigger); |
106 | local->tpt_led_trigger = NULL; | 185 | local->tpt_led_trigger = NULL; |
107 | } | 186 | } |
@@ -110,58 +189,50 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
110 | 189 | ||
111 | void ieee80211_led_exit(struct ieee80211_local *local) | 190 | void ieee80211_led_exit(struct ieee80211_local *local) |
112 | { | 191 | { |
113 | if (local->radio_led) { | 192 | if (local->radio_led.name) |
114 | led_trigger_unregister(local->radio_led); | 193 | led_trigger_unregister(&local->radio_led); |
115 | kfree(local->radio_led); | 194 | if (local->assoc_led.name) |
116 | } | 195 | led_trigger_unregister(&local->assoc_led); |
117 | if (local->assoc_led) { | 196 | if (local->tx_led.name) |
118 | led_trigger_unregister(local->assoc_led); | 197 | led_trigger_unregister(&local->tx_led); |
119 | kfree(local->assoc_led); | 198 | if (local->rx_led.name) |
120 | } | 199 | led_trigger_unregister(&local->rx_led); |
121 | if (local->tx_led) { | ||
122 | led_trigger_unregister(local->tx_led); | ||
123 | kfree(local->tx_led); | ||
124 | } | ||
125 | if (local->rx_led) { | ||
126 | led_trigger_unregister(local->rx_led); | ||
127 | kfree(local->rx_led); | ||
128 | } | ||
129 | 200 | ||
130 | if (local->tpt_led_trigger) { | 201 | if (local->tpt_led_trigger) { |
131 | led_trigger_unregister(&local->tpt_led_trigger->trig); | 202 | led_trigger_unregister(&local->tpt_led); |
132 | kfree(local->tpt_led_trigger); | 203 | kfree(local->tpt_led_trigger); |
133 | } | 204 | } |
134 | } | 205 | } |
135 | 206 | ||
136 | char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | 207 | const char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) |
137 | { | 208 | { |
138 | struct ieee80211_local *local = hw_to_local(hw); | 209 | struct ieee80211_local *local = hw_to_local(hw); |
139 | 210 | ||
140 | return local->radio_led_name; | 211 | return local->radio_led.name; |
141 | } | 212 | } |
142 | EXPORT_SYMBOL(__ieee80211_get_radio_led_name); | 213 | EXPORT_SYMBOL(__ieee80211_get_radio_led_name); |
143 | 214 | ||
144 | char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | 215 | const char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) |
145 | { | 216 | { |
146 | struct ieee80211_local *local = hw_to_local(hw); | 217 | struct ieee80211_local *local = hw_to_local(hw); |
147 | 218 | ||
148 | return local->assoc_led_name; | 219 | return local->assoc_led.name; |
149 | } | 220 | } |
150 | EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); | 221 | EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); |
151 | 222 | ||
152 | char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | 223 | const char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw) |
153 | { | 224 | { |
154 | struct ieee80211_local *local = hw_to_local(hw); | 225 | struct ieee80211_local *local = hw_to_local(hw); |
155 | 226 | ||
156 | return local->tx_led_name; | 227 | return local->tx_led.name; |
157 | } | 228 | } |
158 | EXPORT_SYMBOL(__ieee80211_get_tx_led_name); | 229 | EXPORT_SYMBOL(__ieee80211_get_tx_led_name); |
159 | 230 | ||
160 | char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | 231 | const char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw) |
161 | { | 232 | { |
162 | struct ieee80211_local *local = hw_to_local(hw); | 233 | struct ieee80211_local *local = hw_to_local(hw); |
163 | 234 | ||
164 | return local->rx_led_name; | 235 | return local->rx_led.name; |
165 | } | 236 | } |
166 | EXPORT_SYMBOL(__ieee80211_get_rx_led_name); | 237 | EXPORT_SYMBOL(__ieee80211_get_rx_led_name); |
167 | 238 | ||
@@ -211,10 +282,11 @@ static void tpt_trig_timer(unsigned long data) | |||
211 | read_unlock(&tpt_trig->trig.leddev_list_lock); | 282 | read_unlock(&tpt_trig->trig.leddev_list_lock); |
212 | } | 283 | } |
213 | 284 | ||
214 | char *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, | 285 | const char * |
215 | unsigned int flags, | 286 | __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, |
216 | const struct ieee80211_tpt_blink *blink_table, | 287 | unsigned int flags, |
217 | unsigned int blink_table_len) | 288 | const struct ieee80211_tpt_blink *blink_table, |
289 | unsigned int blink_table_len) | ||
218 | { | 290 | { |
219 | struct ieee80211_local *local = hw_to_local(hw); | 291 | struct ieee80211_local *local = hw_to_local(hw); |
220 | struct tpt_led_trigger *tpt_trig; | 292 | struct tpt_led_trigger *tpt_trig; |
@@ -229,7 +301,7 @@ char *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, | |||
229 | snprintf(tpt_trig->name, sizeof(tpt_trig->name), | 301 | snprintf(tpt_trig->name, sizeof(tpt_trig->name), |
230 | "%stpt", wiphy_name(local->hw.wiphy)); | 302 | "%stpt", wiphy_name(local->hw.wiphy)); |
231 | 303 | ||
232 | tpt_trig->trig.name = tpt_trig->name; | 304 | local->tpt_led.name = tpt_trig->name; |
233 | 305 | ||
234 | tpt_trig->blink_table = blink_table; | 306 | tpt_trig->blink_table = blink_table; |
235 | tpt_trig->blink_table_len = blink_table_len; | 307 | tpt_trig->blink_table_len = blink_table_len; |
diff --git a/net/mac80211/led.h b/net/mac80211/led.h index 89f4344f13b9..a7893a1ac98b 100644 --- a/net/mac80211/led.h +++ b/net/mac80211/led.h | |||
@@ -11,25 +11,42 @@ | |||
11 | #include <linux/leds.h> | 11 | #include <linux/leds.h> |
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | 13 | ||
14 | #define MAC80211_BLINK_DELAY 50 /* ms */ | ||
15 | |||
16 | static inline void ieee80211_led_rx(struct ieee80211_local *local) | ||
17 | { | ||
18 | #ifdef CONFIG_MAC80211_LEDS | ||
19 | unsigned long led_delay = MAC80211_BLINK_DELAY; | ||
20 | |||
21 | if (!atomic_read(&local->rx_led_active)) | ||
22 | return; | ||
23 | led_trigger_blink_oneshot(&local->rx_led, &led_delay, &led_delay, 0); | ||
24 | #endif | ||
25 | } | ||
26 | |||
27 | static inline void ieee80211_led_tx(struct ieee80211_local *local) | ||
28 | { | ||
29 | #ifdef CONFIG_MAC80211_LEDS | ||
30 | unsigned long led_delay = MAC80211_BLINK_DELAY; | ||
31 | |||
32 | if (!atomic_read(&local->tx_led_active)) | ||
33 | return; | ||
34 | led_trigger_blink_oneshot(&local->tx_led, &led_delay, &led_delay, 0); | ||
35 | #endif | ||
36 | } | ||
37 | |||
14 | #ifdef CONFIG_MAC80211_LEDS | 38 | #ifdef CONFIG_MAC80211_LEDS |
15 | void ieee80211_led_rx(struct ieee80211_local *local); | ||
16 | void ieee80211_led_tx(struct ieee80211_local *local); | ||
17 | void ieee80211_led_assoc(struct ieee80211_local *local, | 39 | void ieee80211_led_assoc(struct ieee80211_local *local, |
18 | bool associated); | 40 | bool associated); |
19 | void ieee80211_led_radio(struct ieee80211_local *local, | 41 | void ieee80211_led_radio(struct ieee80211_local *local, |
20 | bool enabled); | 42 | bool enabled); |
21 | void ieee80211_led_names(struct ieee80211_local *local); | 43 | void ieee80211_alloc_led_names(struct ieee80211_local *local); |
44 | void ieee80211_free_led_names(struct ieee80211_local *local); | ||
22 | void ieee80211_led_init(struct ieee80211_local *local); | 45 | void ieee80211_led_init(struct ieee80211_local *local); |
23 | void ieee80211_led_exit(struct ieee80211_local *local); | 46 | void ieee80211_led_exit(struct ieee80211_local *local); |
24 | void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | 47 | void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, |
25 | unsigned int types_on, unsigned int types_off); | 48 | unsigned int types_on, unsigned int types_off); |
26 | #else | 49 | #else |
27 | static inline void ieee80211_led_rx(struct ieee80211_local *local) | ||
28 | { | ||
29 | } | ||
30 | static inline void ieee80211_led_tx(struct ieee80211_local *local) | ||
31 | { | ||
32 | } | ||
33 | static inline void ieee80211_led_assoc(struct ieee80211_local *local, | 50 | static inline void ieee80211_led_assoc(struct ieee80211_local *local, |
34 | bool associated) | 51 | bool associated) |
35 | { | 52 | { |
@@ -38,7 +55,10 @@ static inline void ieee80211_led_radio(struct ieee80211_local *local, | |||
38 | bool enabled) | 55 | bool enabled) |
39 | { | 56 | { |
40 | } | 57 | } |
41 | static inline void ieee80211_led_names(struct ieee80211_local *local) | 58 | static inline void ieee80211_alloc_led_names(struct ieee80211_local *local) |
59 | { | ||
60 | } | ||
61 | static inline void ieee80211_free_led_names(struct ieee80211_local *local) | ||
42 | { | 62 | { |
43 | } | 63 | } |
44 | static inline void ieee80211_led_init(struct ieee80211_local *local) | 64 | static inline void ieee80211_led_init(struct ieee80211_local *local) |
@@ -58,7 +78,7 @@ static inline void | |||
58 | ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) | 78 | ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) |
59 | { | 79 | { |
60 | #ifdef CONFIG_MAC80211_LEDS | 80 | #ifdef CONFIG_MAC80211_LEDS |
61 | if (local->tpt_led_trigger && ieee80211_is_data(fc)) | 81 | if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active)) |
62 | local->tpt_led_trigger->tx_bytes += bytes; | 82 | local->tpt_led_trigger->tx_bytes += bytes; |
63 | #endif | 83 | #endif |
64 | } | 84 | } |
@@ -67,7 +87,7 @@ static inline void | |||
67 | ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) | 87 | ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) |
68 | { | 88 | { |
69 | #ifdef CONFIG_MAC80211_LEDS | 89 | #ifdef CONFIG_MAC80211_LEDS |
70 | if (local->tpt_led_trigger && ieee80211_is_data(fc)) | 90 | if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active)) |
71 | local->tpt_led_trigger->rx_bytes += bytes; | 91 | local->tpt_led_trigger->rx_bytes += bytes; |
72 | #endif | 92 | #endif |
73 | } | 93 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index df3051d96aff..3c956c5f99b2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -41,9 +41,6 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
41 | unsigned int changed_flags; | 41 | unsigned int changed_flags; |
42 | unsigned int new_flags = 0; | 42 | unsigned int new_flags = 0; |
43 | 43 | ||
44 | if (atomic_read(&local->iff_promiscs)) | ||
45 | new_flags |= FIF_PROMISC_IN_BSS; | ||
46 | |||
47 | if (atomic_read(&local->iff_allmultis)) | 44 | if (atomic_read(&local->iff_allmultis)) |
48 | new_flags |= FIF_ALLMULTI; | 45 | new_flags |= FIF_ALLMULTI; |
49 | 46 | ||
@@ -646,7 +643,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, | |||
646 | skb_queue_head_init(&local->skb_queue); | 643 | skb_queue_head_init(&local->skb_queue); |
647 | skb_queue_head_init(&local->skb_queue_unreliable); | 644 | skb_queue_head_init(&local->skb_queue_unreliable); |
648 | 645 | ||
649 | ieee80211_led_names(local); | 646 | ieee80211_alloc_led_names(local); |
650 | 647 | ||
651 | ieee80211_roc_setup(local); | 648 | ieee80211_roc_setup(local); |
652 | 649 | ||
@@ -771,8 +768,11 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | |||
771 | suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; | 768 | suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; |
772 | } | 769 | } |
773 | 770 | ||
774 | for (r = 0; r < local->hw.n_cipher_schemes; r++) | 771 | for (r = 0; r < local->hw.n_cipher_schemes; r++) { |
775 | suites[w++] = cs[r].cipher; | 772 | suites[w++] = cs[r].cipher; |
773 | if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | } | 776 | } |
777 | 777 | ||
778 | local->hw.wiphy->cipher_suites = suites; | 778 | local->hw.wiphy->cipher_suites = suites; |
@@ -840,7 +840,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
840 | 840 | ||
841 | /* Only HW csum features are currently compatible with mac80211 */ | 841 | /* Only HW csum features are currently compatible with mac80211 */ |
842 | feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | 842 | feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
843 | NETIF_F_HW_CSUM; | 843 | NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | |
844 | NETIF_F_GSO_SOFTWARE; | ||
844 | if (WARN_ON(hw->netdev_features & ~feature_whitelist)) | 845 | if (WARN_ON(hw->netdev_features & ~feature_whitelist)) |
845 | return -EINVAL; | 846 | return -EINVAL; |
846 | 847 | ||
@@ -1209,6 +1210,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
1209 | 1210 | ||
1210 | sta_info_stop(local); | 1211 | sta_info_stop(local); |
1211 | 1212 | ||
1213 | ieee80211_free_led_names(local); | ||
1214 | |||
1212 | wiphy_free(local->hw.wiphy); | 1215 | wiphy_free(local->hw.wiphy); |
1213 | } | 1216 | } |
1214 | EXPORT_SYMBOL(ieee80211_free_hw); | 1217 | EXPORT_SYMBOL(ieee80211_free_hw); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 60d737f144e3..ac843fc88745 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -72,10 +72,11 @@ static bool rssi_threshold_check(struct ieee80211_sub_if_data *sdata, | |||
72 | * | 72 | * |
73 | * @sta: mesh peer link to restart | 73 | * @sta: mesh peer link to restart |
74 | * | 74 | * |
75 | * Locking: this function must be called holding sta->lock | 75 | * Locking: this function must be called holding sta->plink_lock |
76 | */ | 76 | */ |
77 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) | 77 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) |
78 | { | 78 | { |
79 | lockdep_assert_held(&sta->plink_lock); | ||
79 | sta->plink_state = NL80211_PLINK_LISTEN; | 80 | sta->plink_state = NL80211_PLINK_LISTEN; |
80 | sta->llid = sta->plid = sta->reason = 0; | 81 | sta->llid = sta->plid = sta->reason = 0; |
81 | sta->plink_retries = 0; | 82 | sta->plink_retries = 0; |
@@ -213,13 +214,15 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
213 | * All mesh paths with this peer as next hop will be flushed | 214 | * All mesh paths with this peer as next hop will be flushed |
214 | * Returns beacon changed flag if the beacon content changed. | 215 | * Returns beacon changed flag if the beacon content changed. |
215 | * | 216 | * |
216 | * Locking: the caller must hold sta->lock | 217 | * Locking: the caller must hold sta->plink_lock |
217 | */ | 218 | */ |
218 | static u32 __mesh_plink_deactivate(struct sta_info *sta) | 219 | static u32 __mesh_plink_deactivate(struct sta_info *sta) |
219 | { | 220 | { |
220 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 221 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
221 | u32 changed = 0; | 222 | u32 changed = 0; |
222 | 223 | ||
224 | lockdep_assert_held(&sta->plink_lock); | ||
225 | |||
223 | if (sta->plink_state == NL80211_PLINK_ESTAB) | 226 | if (sta->plink_state == NL80211_PLINK_ESTAB) |
224 | changed = mesh_plink_dec_estab_count(sdata); | 227 | changed = mesh_plink_dec_estab_count(sdata); |
225 | sta->plink_state = NL80211_PLINK_BLOCKED; | 228 | sta->plink_state = NL80211_PLINK_BLOCKED; |
@@ -244,13 +247,13 @@ u32 mesh_plink_deactivate(struct sta_info *sta) | |||
244 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 247 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
245 | u32 changed; | 248 | u32 changed; |
246 | 249 | ||
247 | spin_lock_bh(&sta->lock); | 250 | spin_lock_bh(&sta->plink_lock); |
248 | changed = __mesh_plink_deactivate(sta); | 251 | changed = __mesh_plink_deactivate(sta); |
249 | sta->reason = WLAN_REASON_MESH_PEER_CANCELED; | 252 | sta->reason = WLAN_REASON_MESH_PEER_CANCELED; |
250 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 253 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
251 | sta->sta.addr, sta->llid, sta->plid, | 254 | sta->sta.addr, sta->llid, sta->plid, |
252 | sta->reason); | 255 | sta->reason); |
253 | spin_unlock_bh(&sta->lock); | 256 | spin_unlock_bh(&sta->plink_lock); |
254 | 257 | ||
255 | return changed; | 258 | return changed; |
256 | } | 259 | } |
@@ -387,7 +390,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
387 | sband = local->hw.wiphy->bands[band]; | 390 | sband = local->hw.wiphy->bands[band]; |
388 | rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); | 391 | rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); |
389 | 392 | ||
390 | spin_lock_bh(&sta->lock); | 393 | spin_lock_bh(&sta->plink_lock); |
391 | sta->last_rx = jiffies; | 394 | sta->last_rx = jiffies; |
392 | 395 | ||
393 | /* rates and capabilities don't change during peering */ | 396 | /* rates and capabilities don't change during peering */ |
@@ -419,7 +422,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
419 | else | 422 | else |
420 | rate_control_rate_update(local, sband, sta, changed); | 423 | rate_control_rate_update(local, sband, sta, changed); |
421 | out: | 424 | out: |
422 | spin_unlock_bh(&sta->lock); | 425 | spin_unlock_bh(&sta->plink_lock); |
423 | } | 426 | } |
424 | 427 | ||
425 | static struct sta_info * | 428 | static struct sta_info * |
@@ -552,7 +555,7 @@ static void mesh_plink_timer(unsigned long data) | |||
552 | if (sta->sdata->local->quiescing) | 555 | if (sta->sdata->local->quiescing) |
553 | return; | 556 | return; |
554 | 557 | ||
555 | spin_lock_bh(&sta->lock); | 558 | spin_lock_bh(&sta->plink_lock); |
556 | 559 | ||
557 | /* If a timer fires just before a state transition on another CPU, | 560 | /* If a timer fires just before a state transition on another CPU, |
558 | * we may have already extended the timeout and changed state by the | 561 | * we may have already extended the timeout and changed state by the |
@@ -563,7 +566,7 @@ static void mesh_plink_timer(unsigned long data) | |||
563 | mpl_dbg(sta->sdata, | 566 | mpl_dbg(sta->sdata, |
564 | "Ignoring timer for %pM in state %s (timer adjusted)", | 567 | "Ignoring timer for %pM in state %s (timer adjusted)", |
565 | sta->sta.addr, mplstates[sta->plink_state]); | 568 | sta->sta.addr, mplstates[sta->plink_state]); |
566 | spin_unlock_bh(&sta->lock); | 569 | spin_unlock_bh(&sta->plink_lock); |
567 | return; | 570 | return; |
568 | } | 571 | } |
569 | 572 | ||
@@ -573,7 +576,7 @@ static void mesh_plink_timer(unsigned long data) | |||
573 | mpl_dbg(sta->sdata, | 576 | mpl_dbg(sta->sdata, |
574 | "Ignoring timer for %pM in state %s (timer deleted)", | 577 | "Ignoring timer for %pM in state %s (timer deleted)", |
575 | sta->sta.addr, mplstates[sta->plink_state]); | 578 | sta->sta.addr, mplstates[sta->plink_state]); |
576 | spin_unlock_bh(&sta->lock); | 579 | spin_unlock_bh(&sta->plink_lock); |
577 | return; | 580 | return; |
578 | } | 581 | } |
579 | 582 | ||
@@ -619,7 +622,7 @@ static void mesh_plink_timer(unsigned long data) | |||
619 | default: | 622 | default: |
620 | break; | 623 | break; |
621 | } | 624 | } |
622 | spin_unlock_bh(&sta->lock); | 625 | spin_unlock_bh(&sta->plink_lock); |
623 | if (action) | 626 | if (action) |
624 | mesh_plink_frame_tx(sdata, action, sta->sta.addr, | 627 | mesh_plink_frame_tx(sdata, action, sta->sta.addr, |
625 | sta->llid, sta->plid, reason); | 628 | sta->llid, sta->plid, reason); |
@@ -674,16 +677,16 @@ u32 mesh_plink_open(struct sta_info *sta) | |||
674 | if (!test_sta_flag(sta, WLAN_STA_AUTH)) | 677 | if (!test_sta_flag(sta, WLAN_STA_AUTH)) |
675 | return 0; | 678 | return 0; |
676 | 679 | ||
677 | spin_lock_bh(&sta->lock); | 680 | spin_lock_bh(&sta->plink_lock); |
678 | sta->llid = mesh_get_new_llid(sdata); | 681 | sta->llid = mesh_get_new_llid(sdata); |
679 | if (sta->plink_state != NL80211_PLINK_LISTEN && | 682 | if (sta->plink_state != NL80211_PLINK_LISTEN && |
680 | sta->plink_state != NL80211_PLINK_BLOCKED) { | 683 | sta->plink_state != NL80211_PLINK_BLOCKED) { |
681 | spin_unlock_bh(&sta->lock); | 684 | spin_unlock_bh(&sta->plink_lock); |
682 | return 0; | 685 | return 0; |
683 | } | 686 | } |
684 | sta->plink_state = NL80211_PLINK_OPN_SNT; | 687 | sta->plink_state = NL80211_PLINK_OPN_SNT; |
685 | mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout); | 688 | mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout); |
686 | spin_unlock_bh(&sta->lock); | 689 | spin_unlock_bh(&sta->plink_lock); |
687 | mpl_dbg(sdata, | 690 | mpl_dbg(sdata, |
688 | "Mesh plink: starting establishment with %pM\n", | 691 | "Mesh plink: starting establishment with %pM\n", |
689 | sta->sta.addr); | 692 | sta->sta.addr); |
@@ -700,10 +703,10 @@ u32 mesh_plink_block(struct sta_info *sta) | |||
700 | { | 703 | { |
701 | u32 changed; | 704 | u32 changed; |
702 | 705 | ||
703 | spin_lock_bh(&sta->lock); | 706 | spin_lock_bh(&sta->plink_lock); |
704 | changed = __mesh_plink_deactivate(sta); | 707 | changed = __mesh_plink_deactivate(sta); |
705 | sta->plink_state = NL80211_PLINK_BLOCKED; | 708 | sta->plink_state = NL80211_PLINK_BLOCKED; |
706 | spin_unlock_bh(&sta->lock); | 709 | spin_unlock_bh(&sta->plink_lock); |
707 | 710 | ||
708 | return changed; | 711 | return changed; |
709 | } | 712 | } |
@@ -758,7 +761,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, | |||
758 | mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr, | 761 | mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr, |
759 | mplstates[sta->plink_state], mplevents[event]); | 762 | mplstates[sta->plink_state], mplevents[event]); |
760 | 763 | ||
761 | spin_lock_bh(&sta->lock); | 764 | spin_lock_bh(&sta->plink_lock); |
762 | switch (sta->plink_state) { | 765 | switch (sta->plink_state) { |
763 | case NL80211_PLINK_LISTEN: | 766 | case NL80211_PLINK_LISTEN: |
764 | switch (event) { | 767 | switch (event) { |
@@ -872,7 +875,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, | |||
872 | */ | 875 | */ |
873 | break; | 876 | break; |
874 | } | 877 | } |
875 | spin_unlock_bh(&sta->lock); | 878 | spin_unlock_bh(&sta->plink_lock); |
876 | if (action) { | 879 | if (action) { |
877 | mesh_plink_frame_tx(sdata, action, sta->sta.addr, | 880 | mesh_plink_frame_tx(sdata, action, sta->sta.addr, |
878 | sta->llid, sta->plid, sta->reason); | 881 | sta->llid, sta->plid, sta->reason); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 26053bf2faa8..3294666f599c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -4307,15 +4307,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
4307 | } | 4307 | } |
4308 | 4308 | ||
4309 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 4309 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, |
4310 | struct cfg80211_bss *cbss, bool assoc) | 4310 | struct cfg80211_bss *cbss, bool assoc, |
4311 | bool override) | ||
4311 | { | 4312 | { |
4312 | struct ieee80211_local *local = sdata->local; | 4313 | struct ieee80211_local *local = sdata->local; |
4313 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4314 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
4314 | struct ieee80211_bss *bss = (void *)cbss->priv; | 4315 | struct ieee80211_bss *bss = (void *)cbss->priv; |
4315 | struct sta_info *new_sta = NULL; | 4316 | struct sta_info *new_sta = NULL; |
4316 | struct ieee80211_supported_band *sband; | 4317 | struct ieee80211_supported_band *sband; |
4317 | struct ieee80211_sta_ht_cap sta_ht_cap; | 4318 | bool have_sta = false; |
4318 | bool have_sta = false, is_override = false; | ||
4319 | int err; | 4319 | int err; |
4320 | 4320 | ||
4321 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 4321 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
@@ -4335,14 +4335,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
4335 | return -ENOMEM; | 4335 | return -ENOMEM; |
4336 | } | 4336 | } |
4337 | 4337 | ||
4338 | memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); | 4338 | if (new_sta || override) { |
4339 | ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); | ||
4340 | |||
4341 | is_override = (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) != | ||
4342 | (sband->ht_cap.cap & | ||
4343 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
4344 | |||
4345 | if (new_sta || is_override) { | ||
4346 | err = ieee80211_prep_channel(sdata, cbss); | 4339 | err = ieee80211_prep_channel(sdata, cbss); |
4347 | if (err) { | 4340 | if (err) { |
4348 | if (new_sta) | 4341 | if (new_sta) |
@@ -4552,7 +4545,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
4552 | 4545 | ||
4553 | sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); | 4546 | sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); |
4554 | 4547 | ||
4555 | err = ieee80211_prep_connection(sdata, req->bss, false); | 4548 | err = ieee80211_prep_connection(sdata, req->bss, false, false); |
4556 | if (err) | 4549 | if (err) |
4557 | goto err_clear; | 4550 | goto err_clear; |
4558 | 4551 | ||
@@ -4624,6 +4617,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4624 | struct ieee80211_supported_band *sband; | 4617 | struct ieee80211_supported_band *sband; |
4625 | const u8 *ssidie, *ht_ie, *vht_ie; | 4618 | const u8 *ssidie, *ht_ie, *vht_ie; |
4626 | int i, err; | 4619 | int i, err; |
4620 | bool override = false; | ||
4627 | 4621 | ||
4628 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); | 4622 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); |
4629 | if (!assoc_data) | 4623 | if (!assoc_data) |
@@ -4728,14 +4722,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4728 | } | 4722 | } |
4729 | } | 4723 | } |
4730 | 4724 | ||
4731 | if (req->flags & ASSOC_REQ_DISABLE_HT) { | ||
4732 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | ||
4733 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
4734 | } | ||
4735 | |||
4736 | if (req->flags & ASSOC_REQ_DISABLE_VHT) | ||
4737 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
4738 | |||
4739 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 4725 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
4740 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 4726 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
4741 | if (!sband->ht_cap.ht_supported || | 4727 | if (!sband->ht_cap.ht_supported || |
@@ -4847,7 +4833,36 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4847 | ifmgd->dtim_period = 0; | 4833 | ifmgd->dtim_period = 0; |
4848 | ifmgd->have_beacon = false; | 4834 | ifmgd->have_beacon = false; |
4849 | 4835 | ||
4850 | err = ieee80211_prep_connection(sdata, req->bss, true); | 4836 | /* override HT/VHT configuration only if the AP and we support it */ |
4837 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
4838 | struct ieee80211_sta_ht_cap sta_ht_cap; | ||
4839 | |||
4840 | if (req->flags & ASSOC_REQ_DISABLE_HT) | ||
4841 | override = true; | ||
4842 | |||
4843 | memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); | ||
4844 | ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); | ||
4845 | |||
4846 | /* check for 40 MHz disable override */ | ||
4847 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ) && | ||
4848 | sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && | ||
4849 | !(sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) | ||
4850 | override = true; | ||
4851 | |||
4852 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | ||
4853 | req->flags & ASSOC_REQ_DISABLE_VHT) | ||
4854 | override = true; | ||
4855 | } | ||
4856 | |||
4857 | if (req->flags & ASSOC_REQ_DISABLE_HT) { | ||
4858 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | ||
4859 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
4860 | } | ||
4861 | |||
4862 | if (req->flags & ASSOC_REQ_DISABLE_VHT) | ||
4863 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
4864 | |||
4865 | err = ieee80211_prep_connection(sdata, req->bss, true, override); | ||
4851 | if (err) | 4866 | if (err) |
4852 | goto err_clear; | 4867 | goto err_clear; |
4853 | 4868 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index d53355b011f5..de69adf24f53 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -683,7 +683,13 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
683 | if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | 683 | if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
684 | return; | 684 | return; |
685 | 685 | ||
686 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); | 686 | if (ista) { |
687 | spin_lock_bh(&sta->rate_ctrl_lock); | ||
688 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); | ||
689 | spin_unlock_bh(&sta->rate_ctrl_lock); | ||
690 | } else { | ||
691 | ref->ops->get_rate(ref->priv, NULL, NULL, txrc); | ||
692 | } | ||
687 | 693 | ||
688 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE) | 694 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE) |
689 | return; | 695 | return; |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 38652f09feaf..25c9be5dd7fd 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -42,10 +42,12 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, | |||
42 | if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) | 42 | if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) |
43 | return; | 43 | return; |
44 | 44 | ||
45 | spin_lock_bh(&sta->rate_ctrl_lock); | ||
45 | if (ref->ops->tx_status) | 46 | if (ref->ops->tx_status) |
46 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | 47 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
47 | else | 48 | else |
48 | ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); | 49 | ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); |
50 | spin_unlock_bh(&sta->rate_ctrl_lock); | ||
49 | } | 51 | } |
50 | 52 | ||
51 | static inline void | 53 | static inline void |
@@ -64,7 +66,9 @@ rate_control_tx_status_noskb(struct ieee80211_local *local, | |||
64 | if (WARN_ON_ONCE(!ref->ops->tx_status_noskb)) | 66 | if (WARN_ON_ONCE(!ref->ops->tx_status_noskb)) |
65 | return; | 67 | return; |
66 | 68 | ||
69 | spin_lock_bh(&sta->rate_ctrl_lock); | ||
67 | ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); | 70 | ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); |
71 | spin_unlock_bh(&sta->rate_ctrl_lock); | ||
68 | } | 72 | } |
69 | 73 | ||
70 | static inline void rate_control_rate_init(struct sta_info *sta) | 74 | static inline void rate_control_rate_init(struct sta_info *sta) |
@@ -91,8 +95,10 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
91 | 95 | ||
92 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; | 96 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; |
93 | 97 | ||
98 | spin_lock_bh(&sta->rate_ctrl_lock); | ||
94 | ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, | 99 | ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, |
95 | priv_sta); | 100 | priv_sta); |
101 | spin_unlock_bh(&sta->rate_ctrl_lock); | ||
96 | rcu_read_unlock(); | 102 | rcu_read_unlock(); |
97 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); | 103 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); |
98 | } | 104 | } |
@@ -115,18 +121,20 @@ static inline void rate_control_rate_update(struct ieee80211_local *local, | |||
115 | return; | 121 | return; |
116 | } | 122 | } |
117 | 123 | ||
124 | spin_lock_bh(&sta->rate_ctrl_lock); | ||
118 | ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, | 125 | ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, |
119 | ista, priv_sta, changed); | 126 | ista, priv_sta, changed); |
127 | spin_unlock_bh(&sta->rate_ctrl_lock); | ||
120 | rcu_read_unlock(); | 128 | rcu_read_unlock(); |
121 | } | 129 | } |
122 | drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); | 130 | drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); |
123 | } | 131 | } |
124 | 132 | ||
125 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 133 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
126 | struct ieee80211_sta *sta, | 134 | struct sta_info *sta, gfp_t gfp) |
127 | gfp_t gfp) | ||
128 | { | 135 | { |
129 | return ref->ops->alloc_sta(ref->priv, sta, gfp); | 136 | spin_lock_init(&sta->rate_ctrl_lock); |
137 | return ref->ops->alloc_sta(ref->priv, &sta->sta, gfp); | ||
130 | } | 138 | } |
131 | 139 | ||
132 | static inline void rate_control_free_sta(struct sta_info *sta) | 140 | static inline void rate_control_free_sta(struct sta_info *sta) |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 260eed45b6d2..aa35977a9c4d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -32,6 +32,16 @@ | |||
32 | #include "wme.h" | 32 | #include "wme.h" |
33 | #include "rate.h" | 33 | #include "rate.h" |
34 | 34 | ||
35 | static inline void ieee80211_rx_stats(struct net_device *dev, u32 len) | ||
36 | { | ||
37 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); | ||
38 | |||
39 | u64_stats_update_begin(&tstats->syncp); | ||
40 | tstats->rx_packets++; | ||
41 | tstats->rx_bytes += len; | ||
42 | u64_stats_update_end(&tstats->syncp); | ||
43 | } | ||
44 | |||
35 | /* | 45 | /* |
36 | * monitor mode reception | 46 | * monitor mode reception |
37 | * | 47 | * |
@@ -529,8 +539,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
529 | } | 539 | } |
530 | 540 | ||
531 | prev_dev = sdata->dev; | 541 | prev_dev = sdata->dev; |
532 | sdata->dev->stats.rx_packets++; | 542 | ieee80211_rx_stats(sdata->dev, skb->len); |
533 | sdata->dev->stats.rx_bytes += skb->len; | ||
534 | } | 543 | } |
535 | 544 | ||
536 | if (prev_dev) { | 545 | if (prev_dev) { |
@@ -981,7 +990,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
981 | struct sk_buff *skb = rx->skb; | 990 | struct sk_buff *skb = rx->skb; |
982 | struct ieee80211_local *local = rx->local; | 991 | struct ieee80211_local *local = rx->local; |
983 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 992 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
984 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
985 | struct sta_info *sta = rx->sta; | 993 | struct sta_info *sta = rx->sta; |
986 | struct tid_ampdu_rx *tid_agg_rx; | 994 | struct tid_ampdu_rx *tid_agg_rx; |
987 | u16 sc; | 995 | u16 sc; |
@@ -1016,10 +1024,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
1016 | ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) | 1024 | ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) |
1017 | goto dont_reorder; | 1025 | goto dont_reorder; |
1018 | 1026 | ||
1019 | /* not actually part of this BA session */ | ||
1020 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1021 | goto dont_reorder; | ||
1022 | |||
1023 | /* new, potentially un-ordered, ampdu frame - process it */ | 1027 | /* new, potentially un-ordered, ampdu frame - process it */ |
1024 | 1028 | ||
1025 | /* reset session timer */ | 1029 | /* reset session timer */ |
@@ -1073,10 +1077,8 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) | |||
1073 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | 1077 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
1074 | rx->sta->last_seq_ctrl[rx->seqno_idx] == | 1078 | rx->sta->last_seq_ctrl[rx->seqno_idx] == |
1075 | hdr->seq_ctrl)) { | 1079 | hdr->seq_ctrl)) { |
1076 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { | 1080 | I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount); |
1077 | rx->local->dot11FrameDuplicateCount++; | 1081 | rx->sta->num_duplicates++; |
1078 | rx->sta->num_duplicates++; | ||
1079 | } | ||
1080 | return RX_DROP_UNUSABLE; | 1082 | return RX_DROP_UNUSABLE; |
1081 | } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { | 1083 | } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { |
1082 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; | 1084 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; |
@@ -1200,6 +1202,8 @@ static void sta_ps_start(struct sta_info *sta) | |||
1200 | ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", | 1202 | ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", |
1201 | sta->sta.addr, sta->sta.aid); | 1203 | sta->sta.addr, sta->sta.aid); |
1202 | 1204 | ||
1205 | ieee80211_clear_fast_xmit(sta); | ||
1206 | |||
1203 | if (!sta->sta.txq[0]) | 1207 | if (!sta->sta.txq[0]) |
1204 | return; | 1208 | return; |
1205 | 1209 | ||
@@ -1265,7 +1269,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) | |||
1265 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 1269 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
1266 | int tid, ac; | 1270 | int tid, ac; |
1267 | 1271 | ||
1268 | if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH)) | 1272 | if (!rx->sta) |
1269 | return RX_CONTINUE; | 1273 | return RX_CONTINUE; |
1270 | 1274 | ||
1271 | if (sdata->vif.type != NL80211_IFTYPE_AP && | 1275 | if (sdata->vif.type != NL80211_IFTYPE_AP && |
@@ -1367,11 +1371,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1367 | } | 1371 | } |
1368 | } | 1372 | } |
1369 | } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { | 1373 | } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { |
1370 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 1374 | sta->last_rx = jiffies; |
1371 | NL80211_IFTYPE_OCB); | ||
1372 | /* OCB uses wild-card BSSID */ | ||
1373 | if (is_broadcast_ether_addr(bssid)) | ||
1374 | sta->last_rx = jiffies; | ||
1375 | } else if (!is_multicast_ether_addr(hdr->addr1)) { | 1375 | } else if (!is_multicast_ether_addr(hdr->addr1)) { |
1376 | /* | 1376 | /* |
1377 | * Mesh beacons will update last_rx when if they are found to | 1377 | * Mesh beacons will update last_rx when if they are found to |
@@ -1386,9 +1386,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1386 | } | 1386 | } |
1387 | } | 1387 | } |
1388 | 1388 | ||
1389 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1390 | return RX_CONTINUE; | ||
1391 | |||
1392 | if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) | 1389 | if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) |
1393 | ieee80211_sta_rx_notify(rx->sdata, hdr); | 1390 | ieee80211_sta_rx_notify(rx->sdata, hdr); |
1394 | 1391 | ||
@@ -1517,13 +1514,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1517 | * possible. | 1514 | * possible. |
1518 | */ | 1515 | */ |
1519 | 1516 | ||
1520 | /* | ||
1521 | * No point in finding a key and decrypting if the frame is neither | ||
1522 | * addressed to us nor a multicast frame. | ||
1523 | */ | ||
1524 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1525 | return RX_CONTINUE; | ||
1526 | |||
1527 | /* start without a key */ | 1517 | /* start without a key */ |
1528 | rx->key = NULL; | 1518 | rx->key = NULL; |
1529 | fc = hdr->frame_control; | 1519 | fc = hdr->frame_control; |
@@ -1795,7 +1785,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1795 | frag = sc & IEEE80211_SCTL_FRAG; | 1785 | frag = sc & IEEE80211_SCTL_FRAG; |
1796 | 1786 | ||
1797 | if (is_multicast_ether_addr(hdr->addr1)) { | 1787 | if (is_multicast_ether_addr(hdr->addr1)) { |
1798 | rx->local->dot11MulticastReceivedFrameCount++; | 1788 | I802_DEBUG_INC(rx->local->dot11MulticastReceivedFrameCount); |
1799 | goto out_no_led; | 1789 | goto out_no_led; |
1800 | } | 1790 | } |
1801 | 1791 | ||
@@ -1878,7 +1868,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1878 | 1868 | ||
1879 | rx->skb = __skb_dequeue(&entry->skb_list); | 1869 | rx->skb = __skb_dequeue(&entry->skb_list); |
1880 | if (skb_tailroom(rx->skb) < entry->extra_len) { | 1870 | if (skb_tailroom(rx->skb) < entry->extra_len) { |
1881 | I802_DEBUG_INC(rx->local->rx_expand_skb_head2); | 1871 | I802_DEBUG_INC(rx->local->rx_expand_skb_head_defrag); |
1882 | if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len, | 1872 | if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len, |
1883 | GFP_ATOMIC))) { | 1873 | GFP_ATOMIC))) { |
1884 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 1874 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
@@ -2054,18 +2044,15 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
2054 | struct sk_buff *skb, *xmit_skb; | 2044 | struct sk_buff *skb, *xmit_skb; |
2055 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 2045 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
2056 | struct sta_info *dsta; | 2046 | struct sta_info *dsta; |
2057 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
2058 | |||
2059 | dev->stats.rx_packets++; | ||
2060 | dev->stats.rx_bytes += rx->skb->len; | ||
2061 | 2047 | ||
2062 | skb = rx->skb; | 2048 | skb = rx->skb; |
2063 | xmit_skb = NULL; | 2049 | xmit_skb = NULL; |
2064 | 2050 | ||
2051 | ieee80211_rx_stats(dev, skb->len); | ||
2052 | |||
2065 | if ((sdata->vif.type == NL80211_IFTYPE_AP || | 2053 | if ((sdata->vif.type == NL80211_IFTYPE_AP || |
2066 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && | 2054 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
2067 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && | 2055 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && |
2068 | (status->rx_flags & IEEE80211_RX_RA_MATCH) && | ||
2069 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) { | 2056 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) { |
2070 | if (is_multicast_ether_addr(ehdr->h_dest)) { | 2057 | if (is_multicast_ether_addr(ehdr->h_dest)) { |
2071 | /* | 2058 | /* |
@@ -2206,7 +2193,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2206 | struct sk_buff *skb = rx->skb, *fwd_skb; | 2193 | struct sk_buff *skb = rx->skb, *fwd_skb; |
2207 | struct ieee80211_local *local = rx->local; | 2194 | struct ieee80211_local *local = rx->local; |
2208 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2195 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
2209 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2210 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 2196 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
2211 | u16 q, hdrlen; | 2197 | u16 q, hdrlen; |
2212 | 2198 | ||
@@ -2237,8 +2223,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2237 | mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr)) | 2223 | mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr)) |
2238 | return RX_DROP_MONITOR; | 2224 | return RX_DROP_MONITOR; |
2239 | 2225 | ||
2240 | if (!ieee80211_is_data(hdr->frame_control) || | 2226 | if (!ieee80211_is_data(hdr->frame_control)) |
2241 | !(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
2242 | return RX_CONTINUE; | 2227 | return RX_CONTINUE; |
2243 | 2228 | ||
2244 | if (!mesh_hdr->ttl) | 2229 | if (!mesh_hdr->ttl) |
@@ -2329,11 +2314,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2329 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); | 2314 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); |
2330 | ieee80211_add_pending_skb(local, fwd_skb); | 2315 | ieee80211_add_pending_skb(local, fwd_skb); |
2331 | out: | 2316 | out: |
2332 | if (is_multicast_ether_addr(hdr->addr1) || | 2317 | if (is_multicast_ether_addr(hdr->addr1)) |
2333 | sdata->dev->flags & IFF_PROMISC) | ||
2334 | return RX_CONTINUE; | 2318 | return RX_CONTINUE; |
2335 | else | 2319 | return RX_DROP_MONITOR; |
2336 | return RX_DROP_MONITOR; | ||
2337 | } | 2320 | } |
2338 | #endif | 2321 | #endif |
2339 | 2322 | ||
@@ -2444,6 +2427,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
2444 | struct { | 2427 | struct { |
2445 | __le16 control, start_seq_num; | 2428 | __le16 control, start_seq_num; |
2446 | } __packed bar_data; | 2429 | } __packed bar_data; |
2430 | struct ieee80211_event event = { | ||
2431 | .type = BAR_RX_EVENT, | ||
2432 | }; | ||
2447 | 2433 | ||
2448 | if (!rx->sta) | 2434 | if (!rx->sta) |
2449 | return RX_DROP_MONITOR; | 2435 | return RX_DROP_MONITOR; |
@@ -2459,6 +2445,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
2459 | return RX_DROP_MONITOR; | 2445 | return RX_DROP_MONITOR; |
2460 | 2446 | ||
2461 | start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4; | 2447 | start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4; |
2448 | event.u.ba.tid = tid; | ||
2449 | event.u.ba.ssn = start_seq_num; | ||
2450 | event.u.ba.sta = &rx->sta->sta; | ||
2462 | 2451 | ||
2463 | /* reset session timer */ | 2452 | /* reset session timer */ |
2464 | if (tid_agg_rx->timeout) | 2453 | if (tid_agg_rx->timeout) |
@@ -2471,6 +2460,8 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
2471 | start_seq_num, frames); | 2460 | start_seq_num, frames); |
2472 | spin_unlock(&tid_agg_rx->reorder_lock); | 2461 | spin_unlock(&tid_agg_rx->reorder_lock); |
2473 | 2462 | ||
2463 | drv_event_callback(rx->local, rx->sdata, &event); | ||
2464 | |||
2474 | kfree_skb(skb); | 2465 | kfree_skb(skb); |
2475 | return RX_QUEUED; | 2466 | return RX_QUEUED; |
2476 | } | 2467 | } |
@@ -2560,9 +2551,6 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2560 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; | 2551 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; |
2561 | } | 2552 | } |
2562 | 2553 | ||
2563 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
2564 | return RX_DROP_MONITOR; | ||
2565 | |||
2566 | if (ieee80211_drop_unencrypted_mgmt(rx)) | 2554 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
2567 | return RX_DROP_UNUSABLE; | 2555 | return RX_DROP_UNUSABLE; |
2568 | 2556 | ||
@@ -2590,9 +2578,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2590 | mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) | 2578 | mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) |
2591 | return RX_DROP_UNUSABLE; | 2579 | return RX_DROP_UNUSABLE; |
2592 | 2580 | ||
2593 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
2594 | return RX_DROP_UNUSABLE; | ||
2595 | |||
2596 | switch (mgmt->u.action.category) { | 2581 | switch (mgmt->u.action.category) { |
2597 | case WLAN_CATEGORY_HT: | 2582 | case WLAN_CATEGORY_HT: |
2598 | /* reject HT action frames from stations not supporting HT */ | 2583 | /* reject HT action frames from stations not supporting HT */ |
@@ -3076,8 +3061,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
3076 | } | 3061 | } |
3077 | 3062 | ||
3078 | prev_dev = sdata->dev; | 3063 | prev_dev = sdata->dev; |
3079 | sdata->dev->stats.rx_packets++; | 3064 | ieee80211_rx_stats(sdata->dev, skb->len); |
3080 | sdata->dev->stats.rx_bytes += skb->len; | ||
3081 | } | 3065 | } |
3082 | 3066 | ||
3083 | if (prev_dev) { | 3067 | if (prev_dev) { |
@@ -3245,16 +3229,25 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
3245 | ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames); | 3229 | ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames); |
3246 | spin_unlock(&tid_agg_rx->reorder_lock); | 3230 | spin_unlock(&tid_agg_rx->reorder_lock); |
3247 | 3231 | ||
3232 | if (!skb_queue_empty(&frames)) { | ||
3233 | struct ieee80211_event event = { | ||
3234 | .type = BA_FRAME_TIMEOUT, | ||
3235 | .u.ba.tid = tid, | ||
3236 | .u.ba.sta = &sta->sta, | ||
3237 | }; | ||
3238 | drv_event_callback(rx.local, rx.sdata, &event); | ||
3239 | } | ||
3240 | |||
3248 | ieee80211_rx_handlers(&rx, &frames); | 3241 | ieee80211_rx_handlers(&rx, &frames); |
3249 | } | 3242 | } |
3250 | 3243 | ||
3251 | /* main receive path */ | 3244 | /* main receive path */ |
3252 | 3245 | ||
3253 | static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | 3246 | static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) |
3254 | struct ieee80211_hdr *hdr) | ||
3255 | { | 3247 | { |
3256 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 3248 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
3257 | struct sk_buff *skb = rx->skb; | 3249 | struct sk_buff *skb = rx->skb; |
3250 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
3258 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 3251 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
3259 | u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); | 3252 | u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); |
3260 | int multicast = is_multicast_ether_addr(hdr->addr1); | 3253 | int multicast = is_multicast_ether_addr(hdr->addr1); |
@@ -3263,30 +3256,23 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3263 | case NL80211_IFTYPE_STATION: | 3256 | case NL80211_IFTYPE_STATION: |
3264 | if (!bssid && !sdata->u.mgd.use_4addr) | 3257 | if (!bssid && !sdata->u.mgd.use_4addr) |
3265 | return false; | 3258 | return false; |
3266 | if (!multicast && | 3259 | if (multicast) |
3267 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { | 3260 | return true; |
3268 | if (!(sdata->dev->flags & IFF_PROMISC) || | 3261 | return ether_addr_equal(sdata->vif.addr, hdr->addr1); |
3269 | sdata->u.mgd.use_4addr) | ||
3270 | return false; | ||
3271 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
3272 | } | ||
3273 | break; | ||
3274 | case NL80211_IFTYPE_ADHOC: | 3262 | case NL80211_IFTYPE_ADHOC: |
3275 | if (!bssid) | 3263 | if (!bssid) |
3276 | return false; | 3264 | return false; |
3277 | if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || | 3265 | if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || |
3278 | ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) | 3266 | ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) |
3279 | return false; | 3267 | return false; |
3280 | if (ieee80211_is_beacon(hdr->frame_control)) { | 3268 | if (ieee80211_is_beacon(hdr->frame_control)) |
3281 | return true; | 3269 | return true; |
3282 | } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { | 3270 | if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) |
3283 | return false; | 3271 | return false; |
3284 | } else if (!multicast && | 3272 | if (!multicast && |
3285 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { | 3273 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) |
3286 | if (!(sdata->dev->flags & IFF_PROMISC)) | 3274 | return false; |
3287 | return false; | 3275 | if (!rx->sta) { |
3288 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
3289 | } else if (!rx->sta) { | ||
3290 | int rate_idx; | 3276 | int rate_idx; |
3291 | if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) | 3277 | if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) |
3292 | rate_idx = 0; /* TODO: HT/VHT rates */ | 3278 | rate_idx = 0; /* TODO: HT/VHT rates */ |
@@ -3295,25 +3281,18 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3295 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, | 3281 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, |
3296 | BIT(rate_idx)); | 3282 | BIT(rate_idx)); |
3297 | } | 3283 | } |
3298 | break; | 3284 | return true; |
3299 | case NL80211_IFTYPE_OCB: | 3285 | case NL80211_IFTYPE_OCB: |
3300 | if (!bssid) | 3286 | if (!bssid) |
3301 | return false; | 3287 | return false; |
3302 | if (ieee80211_is_beacon(hdr->frame_control)) { | 3288 | if (ieee80211_is_beacon(hdr->frame_control)) |
3303 | return false; | 3289 | return false; |
3304 | } else if (!is_broadcast_ether_addr(bssid)) { | 3290 | if (!is_broadcast_ether_addr(bssid)) |
3305 | ocb_dbg(sdata, "BSSID mismatch in OCB mode!\n"); | ||
3306 | return false; | 3291 | return false; |
3307 | } else if (!multicast && | 3292 | if (!multicast && |
3308 | !ether_addr_equal(sdata->dev->dev_addr, | 3293 | !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1)) |
3309 | hdr->addr1)) { | 3294 | return false; |
3310 | /* if we are in promisc mode we also accept | 3295 | if (!rx->sta) { |
3311 | * packets not destined for us | ||
3312 | */ | ||
3313 | if (!(sdata->dev->flags & IFF_PROMISC)) | ||
3314 | return false; | ||
3315 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | ||
3316 | } else if (!rx->sta) { | ||
3317 | int rate_idx; | 3296 | int rate_idx; |
3318 | if (status->flag & RX_FLAG_HT) | 3297 | if (status->flag & RX_FLAG_HT) |
3319 | rate_idx = 0; /* TODO: HT rates */ | 3298 | rate_idx = 0; /* TODO: HT rates */ |
@@ -3322,22 +3301,17 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3322 | ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2, | 3301 | ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2, |
3323 | BIT(rate_idx)); | 3302 | BIT(rate_idx)); |
3324 | } | 3303 | } |
3325 | break; | 3304 | return true; |
3326 | case NL80211_IFTYPE_MESH_POINT: | 3305 | case NL80211_IFTYPE_MESH_POINT: |
3327 | if (!multicast && | 3306 | if (multicast) |
3328 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { | 3307 | return true; |
3329 | if (!(sdata->dev->flags & IFF_PROMISC)) | 3308 | return ether_addr_equal(sdata->vif.addr, hdr->addr1); |
3330 | return false; | ||
3331 | |||
3332 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
3333 | } | ||
3334 | break; | ||
3335 | case NL80211_IFTYPE_AP_VLAN: | 3309 | case NL80211_IFTYPE_AP_VLAN: |
3336 | case NL80211_IFTYPE_AP: | 3310 | case NL80211_IFTYPE_AP: |
3337 | if (!bssid) { | 3311 | if (!bssid) |
3338 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | 3312 | return ether_addr_equal(sdata->vif.addr, hdr->addr1); |
3339 | return false; | 3313 | |
3340 | } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { | 3314 | if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { |
3341 | /* | 3315 | /* |
3342 | * Accept public action frames even when the | 3316 | * Accept public action frames even when the |
3343 | * BSSID doesn't match, this is used for P2P | 3317 | * BSSID doesn't match, this is used for P2P |
@@ -3349,10 +3323,10 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3349 | return false; | 3323 | return false; |
3350 | if (ieee80211_is_public_action(hdr, skb->len)) | 3324 | if (ieee80211_is_public_action(hdr, skb->len)) |
3351 | return true; | 3325 | return true; |
3352 | if (!ieee80211_is_beacon(hdr->frame_control)) | 3326 | return ieee80211_is_beacon(hdr->frame_control); |
3353 | return false; | 3327 | } |
3354 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 3328 | |
3355 | } else if (!ieee80211_has_tods(hdr->frame_control)) { | 3329 | if (!ieee80211_has_tods(hdr->frame_control)) { |
3356 | /* ignore data frames to TDLS-peers */ | 3330 | /* ignore data frames to TDLS-peers */ |
3357 | if (ieee80211_is_data(hdr->frame_control)) | 3331 | if (ieee80211_is_data(hdr->frame_control)) |
3358 | return false; | 3332 | return false; |
@@ -3361,30 +3335,22 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3361 | !ether_addr_equal(bssid, hdr->addr1)) | 3335 | !ether_addr_equal(bssid, hdr->addr1)) |
3362 | return false; | 3336 | return false; |
3363 | } | 3337 | } |
3364 | break; | 3338 | return true; |
3365 | case NL80211_IFTYPE_WDS: | 3339 | case NL80211_IFTYPE_WDS: |
3366 | if (bssid || !ieee80211_is_data(hdr->frame_control)) | 3340 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
3367 | return false; | 3341 | return false; |
3368 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) | 3342 | return ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2); |
3369 | return false; | ||
3370 | break; | ||
3371 | case NL80211_IFTYPE_P2P_DEVICE: | 3343 | case NL80211_IFTYPE_P2P_DEVICE: |
3372 | if (!ieee80211_is_public_action(hdr, skb->len) && | 3344 | return ieee80211_is_public_action(hdr, skb->len) || |
3373 | !ieee80211_is_probe_req(hdr->frame_control) && | 3345 | ieee80211_is_probe_req(hdr->frame_control) || |
3374 | !ieee80211_is_probe_resp(hdr->frame_control) && | 3346 | ieee80211_is_probe_resp(hdr->frame_control) || |
3375 | !ieee80211_is_beacon(hdr->frame_control)) | 3347 | ieee80211_is_beacon(hdr->frame_control); |
3376 | return false; | ||
3377 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) && | ||
3378 | !multicast) | ||
3379 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
3380 | break; | ||
3381 | default: | 3348 | default: |
3382 | /* should never get here */ | ||
3383 | WARN_ON_ONCE(1); | ||
3384 | break; | 3349 | break; |
3385 | } | 3350 | } |
3386 | 3351 | ||
3387 | return true; | 3352 | WARN_ON_ONCE(1); |
3353 | return false; | ||
3388 | } | 3354 | } |
3389 | 3355 | ||
3390 | /* | 3356 | /* |
@@ -3398,13 +3364,10 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, | |||
3398 | { | 3364 | { |
3399 | struct ieee80211_local *local = rx->local; | 3365 | struct ieee80211_local *local = rx->local; |
3400 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 3366 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
3401 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
3402 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
3403 | 3367 | ||
3404 | rx->skb = skb; | 3368 | rx->skb = skb; |
3405 | status->rx_flags |= IEEE80211_RX_RA_MATCH; | ||
3406 | 3369 | ||
3407 | if (!prepare_for_handlers(rx, hdr)) | 3370 | if (!ieee80211_accept_frame(rx)) |
3408 | return false; | 3371 | return false; |
3409 | 3372 | ||
3410 | if (!consume) { | 3373 | if (!consume) { |
@@ -3447,7 +3410,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
3447 | rx.local = local; | 3410 | rx.local = local; |
3448 | 3411 | ||
3449 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) | 3412 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
3450 | local->dot11ReceivedFragmentCount++; | 3413 | I802_DEBUG_INC(local->dot11ReceivedFragmentCount); |
3451 | 3414 | ||
3452 | if (ieee80211_is_mgmt(fc)) { | 3415 | if (ieee80211_is_mgmt(fc)) { |
3453 | /* drop frame if too short for header */ | 3416 | /* drop frame if too short for header */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 12971b71d0fa..aec15d746aea 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -70,6 +70,7 @@ static const struct rhashtable_params sta_rht_params = { | |||
70 | .key_offset = offsetof(struct sta_info, sta.addr), | 70 | .key_offset = offsetof(struct sta_info, sta.addr), |
71 | .key_len = ETH_ALEN, | 71 | .key_len = ETH_ALEN, |
72 | .hashfn = sta_addr_hash, | 72 | .hashfn = sta_addr_hash, |
73 | .max_size = CONFIG_MAC80211_STA_HASH_MAX_SIZE, | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* Caller must hold local->sta_mtx */ | 76 | /* Caller must hold local->sta_mtx */ |
@@ -269,7 +270,7 @@ static int sta_prepare_rate_control(struct ieee80211_local *local, | |||
269 | 270 | ||
270 | sta->rate_ctrl = local->rate_ctrl; | 271 | sta->rate_ctrl = local->rate_ctrl; |
271 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 272 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
272 | &sta->sta, gfp); | 273 | sta, gfp); |
273 | if (!sta->rate_ctrl_priv) | 274 | if (!sta->rate_ctrl_priv) |
274 | return -ENOMEM; | 275 | return -ENOMEM; |
275 | 276 | ||
@@ -295,6 +296,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
295 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 296 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
296 | mutex_init(&sta->ampdu_mlme.mtx); | 297 | mutex_init(&sta->ampdu_mlme.mtx); |
297 | #ifdef CONFIG_MAC80211_MESH | 298 | #ifdef CONFIG_MAC80211_MESH |
299 | spin_lock_init(&sta->plink_lock); | ||
298 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 300 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
299 | !sdata->u.mesh.user_mpm) | 301 | !sdata->u.mesh.user_mpm) |
300 | init_timer(&sta->plink_timer); | 302 | init_timer(&sta->plink_timer); |
@@ -1200,6 +1202,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1200 | ps_dbg(sdata, | 1202 | ps_dbg(sdata, |
1201 | "STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n", | 1203 | "STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n", |
1202 | sta->sta.addr, sta->sta.aid, filtered, buffered); | 1204 | sta->sta.addr, sta->sta.aid, filtered, buffered); |
1205 | |||
1206 | ieee80211_check_fast_xmit(sta); | ||
1203 | } | 1207 | } |
1204 | 1208 | ||
1205 | static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | 1209 | static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, |
@@ -1598,6 +1602,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
1598 | 1602 | ||
1599 | if (block) { | 1603 | if (block) { |
1600 | set_sta_flag(sta, WLAN_STA_PS_DRIVER); | 1604 | set_sta_flag(sta, WLAN_STA_PS_DRIVER); |
1605 | ieee80211_clear_fast_xmit(sta); | ||
1601 | return; | 1606 | return; |
1602 | } | 1607 | } |
1603 | 1608 | ||
@@ -1615,6 +1620,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
1615 | ieee80211_queue_work(hw, &sta->drv_deliver_wk); | 1620 | ieee80211_queue_work(hw, &sta->drv_deliver_wk); |
1616 | } else { | 1621 | } else { |
1617 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | 1622 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
1623 | ieee80211_check_fast_xmit(sta); | ||
1618 | } | 1624 | } |
1619 | } | 1625 | } |
1620 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 1626 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
@@ -1719,6 +1725,7 @@ int sta_info_move_state(struct sta_info *sta, | |||
1719 | !sta->sdata->u.vlan.sta)) | 1725 | !sta->sdata->u.vlan.sta)) |
1720 | atomic_dec(&sta->sdata->bss->num_mcast_sta); | 1726 | atomic_dec(&sta->sdata->bss->num_mcast_sta); |
1721 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | 1727 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); |
1728 | ieee80211_clear_fast_xmit(sta); | ||
1722 | } | 1729 | } |
1723 | break; | 1730 | break; |
1724 | case IEEE80211_STA_AUTHORIZED: | 1731 | case IEEE80211_STA_AUTHORIZED: |
@@ -1728,6 +1735,7 @@ int sta_info_move_state(struct sta_info *sta, | |||
1728 | !sta->sdata->u.vlan.sta)) | 1735 | !sta->sdata->u.vlan.sta)) |
1729 | atomic_inc(&sta->sdata->bss->num_mcast_sta); | 1736 | atomic_inc(&sta->sdata->bss->num_mcast_sta); |
1730 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | 1737 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); |
1738 | ieee80211_check_fast_xmit(sta); | ||
1731 | } | 1739 | } |
1732 | break; | 1740 | break; |
1733 | default: | 1741 | default: |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5c164fb3f6c5..9bd1e97876bd 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -241,6 +241,34 @@ struct sta_ampdu_mlme { | |||
241 | /* Value to indicate no TID reservation */ | 241 | /* Value to indicate no TID reservation */ |
242 | #define IEEE80211_TID_UNRESERVED 0xff | 242 | #define IEEE80211_TID_UNRESERVED 0xff |
243 | 243 | ||
244 | #define IEEE80211_FAST_XMIT_MAX_IV 18 | ||
245 | |||
246 | /** | ||
247 | * struct ieee80211_fast_tx - TX fastpath information | ||
248 | * @key: key to use for hw crypto | ||
249 | * @hdr: the 802.11 header to put with the frame | ||
250 | * @hdr_len: actual 802.11 header length | ||
251 | * @sa_offs: offset of the SA | ||
252 | * @da_offs: offset of the DA | ||
253 | * @pn_offs: offset where to put PN for crypto (or 0 if not needed) | ||
254 | * @band: band this will be transmitted on, for tx_info | ||
255 | * @rcu_head: RCU head to free this struct | ||
256 | * | ||
257 | * This struct is small enough so that the common case (maximum crypto | ||
258 | * header length of 8 like for CCMP/GCMP) fits into a single 64-byte | ||
259 | * cache line. | ||
260 | */ | ||
261 | struct ieee80211_fast_tx { | ||
262 | struct ieee80211_key *key; | ||
263 | u8 hdr_len; | ||
264 | u8 sa_offs, da_offs, pn_offs; | ||
265 | u8 band; | ||
266 | u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV + | ||
267 | sizeof(rfc1042_header)]; | ||
268 | |||
269 | struct rcu_head rcu_head; | ||
270 | }; | ||
271 | |||
244 | /** | 272 | /** |
245 | * struct sta_info - STA information | 273 | * struct sta_info - STA information |
246 | * | 274 | * |
@@ -257,6 +285,8 @@ struct sta_ampdu_mlme { | |||
257 | * @gtk: group keys negotiated with this station, if any | 285 | * @gtk: group keys negotiated with this station, if any |
258 | * @gtk_idx: last installed group key index | 286 | * @gtk_idx: last installed group key index |
259 | * @rate_ctrl: rate control algorithm reference | 287 | * @rate_ctrl: rate control algorithm reference |
288 | * @rate_ctrl_lock: spinlock used to protect rate control data | ||
289 | * (data inside the algorithm, so serializes calls there) | ||
260 | * @rate_ctrl_priv: rate control private per-STA pointer | 290 | * @rate_ctrl_priv: rate control private per-STA pointer |
261 | * @last_tx_rate: rate used for last transmit, to report to userspace as | 291 | * @last_tx_rate: rate used for last transmit, to report to userspace as |
262 | * "the" transmit rate | 292 | * "the" transmit rate |
@@ -295,10 +325,10 @@ struct sta_ampdu_mlme { | |||
295 | * @fail_avg: moving percentage of failed MSDUs | 325 | * @fail_avg: moving percentage of failed MSDUs |
296 | * @tx_packets: number of RX/TX MSDUs | 326 | * @tx_packets: number of RX/TX MSDUs |
297 | * @tx_bytes: number of bytes transmitted to this STA | 327 | * @tx_bytes: number of bytes transmitted to this STA |
298 | * @tx_fragments: number of transmitted MPDUs | ||
299 | * @tid_seq: per-TID sequence numbers for sending to this STA | 328 | * @tid_seq: per-TID sequence numbers for sending to this STA |
300 | * @ampdu_mlme: A-MPDU state machine state | 329 | * @ampdu_mlme: A-MPDU state machine state |
301 | * @timer_to_tid: identity mapping to ID timers | 330 | * @timer_to_tid: identity mapping to ID timers |
331 | * @plink_lock: serialize access to plink fields | ||
302 | * @llid: Local link ID | 332 | * @llid: Local link ID |
303 | * @plid: Peer link ID | 333 | * @plid: Peer link ID |
304 | * @reason: Cancel reason on PLINK_HOLDING state | 334 | * @reason: Cancel reason on PLINK_HOLDING state |
@@ -338,6 +368,7 @@ struct sta_ampdu_mlme { | |||
338 | * using IEEE80211_NUM_TID entry for non-QoS frames | 368 | * using IEEE80211_NUM_TID entry for non-QoS frames |
339 | * @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID | 369 | * @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID |
340 | * entry for non-QoS frames | 370 | * entry for non-QoS frames |
371 | * @fast_tx: TX fastpath information | ||
341 | */ | 372 | */ |
342 | struct sta_info { | 373 | struct sta_info { |
343 | /* General information, mostly static */ | 374 | /* General information, mostly static */ |
@@ -352,8 +383,11 @@ struct sta_info { | |||
352 | u8 ptk_idx; | 383 | u8 ptk_idx; |
353 | struct rate_control_ref *rate_ctrl; | 384 | struct rate_control_ref *rate_ctrl; |
354 | void *rate_ctrl_priv; | 385 | void *rate_ctrl_priv; |
386 | spinlock_t rate_ctrl_lock; | ||
355 | spinlock_t lock; | 387 | spinlock_t lock; |
356 | 388 | ||
389 | struct ieee80211_fast_tx __rcu *fast_tx; | ||
390 | |||
357 | struct work_struct drv_deliver_wk; | 391 | struct work_struct drv_deliver_wk; |
358 | 392 | ||
359 | u16 listen_interval; | 393 | u16 listen_interval; |
@@ -400,7 +434,6 @@ struct sta_info { | |||
400 | unsigned int fail_avg; | 434 | unsigned int fail_avg; |
401 | 435 | ||
402 | /* Updated from TX path only, no locking requirements */ | 436 | /* Updated from TX path only, no locking requirements */ |
403 | u32 tx_fragments; | ||
404 | u64 tx_packets[IEEE80211_NUM_ACS]; | 437 | u64 tx_packets[IEEE80211_NUM_ACS]; |
405 | u64 tx_bytes[IEEE80211_NUM_ACS]; | 438 | u64 tx_bytes[IEEE80211_NUM_ACS]; |
406 | struct ieee80211_tx_rate last_tx_rate; | 439 | struct ieee80211_tx_rate last_tx_rate; |
@@ -422,9 +455,10 @@ struct sta_info { | |||
422 | 455 | ||
423 | #ifdef CONFIG_MAC80211_MESH | 456 | #ifdef CONFIG_MAC80211_MESH |
424 | /* | 457 | /* |
425 | * Mesh peer link attributes | 458 | * Mesh peer link attributes, protected by plink_lock. |
426 | * TODO: move to a sub-structure that is referenced with pointer? | 459 | * TODO: move to a sub-structure that is referenced with pointer? |
427 | */ | 460 | */ |
461 | spinlock_t plink_lock; | ||
428 | u16 llid; | 462 | u16 llid; |
429 | u16 plid; | 463 | u16 plid; |
430 | u16 reason; | 464 | u16 reason; |
@@ -432,6 +466,7 @@ struct sta_info { | |||
432 | enum nl80211_plink_state plink_state; | 466 | enum nl80211_plink_state plink_state; |
433 | u32 plink_timeout; | 467 | u32 plink_timeout; |
434 | struct timer_list plink_timer; | 468 | struct timer_list plink_timer; |
469 | |||
435 | s64 t_offset; | 470 | s64 t_offset; |
436 | s64 t_offset_setpoint; | 471 | s64 t_offset_setpoint; |
437 | /* mesh power save */ | 472 | /* mesh power save */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 005fdbe39a8b..461594966b65 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -631,15 +631,15 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, | |||
631 | } | 631 | } |
632 | 632 | ||
633 | if (acked || noack_success) { | 633 | if (acked || noack_success) { |
634 | local->dot11TransmittedFrameCount++; | 634 | I802_DEBUG_INC(local->dot11TransmittedFrameCount); |
635 | if (!pubsta) | 635 | if (!pubsta) |
636 | local->dot11MulticastTransmittedFrameCount++; | 636 | I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount); |
637 | if (retry_count > 0) | 637 | if (retry_count > 0) |
638 | local->dot11RetryCount++; | 638 | I802_DEBUG_INC(local->dot11RetryCount); |
639 | if (retry_count > 1) | 639 | if (retry_count > 1) |
640 | local->dot11MultipleRetryCount++; | 640 | I802_DEBUG_INC(local->dot11MultipleRetryCount); |
641 | } else { | 641 | } else { |
642 | local->dot11FailedCount++; | 642 | I802_DEBUG_INC(local->dot11FailedCount); |
643 | } | 643 | } |
644 | } | 644 | } |
645 | EXPORT_SYMBOL(ieee80211_tx_status_noskb); | 645 | EXPORT_SYMBOL(ieee80211_tx_status_noskb); |
@@ -802,13 +802,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
802 | if ((info->flags & IEEE80211_TX_STAT_ACK) || | 802 | if ((info->flags & IEEE80211_TX_STAT_ACK) || |
803 | (info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) { | 803 | (info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) { |
804 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) { | 804 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) { |
805 | local->dot11TransmittedFrameCount++; | 805 | I802_DEBUG_INC(local->dot11TransmittedFrameCount); |
806 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) | 806 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) |
807 | local->dot11MulticastTransmittedFrameCount++; | 807 | I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount); |
808 | if (retry_count > 0) | 808 | if (retry_count > 0) |
809 | local->dot11RetryCount++; | 809 | I802_DEBUG_INC(local->dot11RetryCount); |
810 | if (retry_count > 1) | 810 | if (retry_count > 1) |
811 | local->dot11MultipleRetryCount++; | 811 | I802_DEBUG_INC(local->dot11MultipleRetryCount); |
812 | } | 812 | } |
813 | 813 | ||
814 | /* This counter shall be incremented for an acknowledged MPDU | 814 | /* This counter shall be incremented for an acknowledged MPDU |
@@ -818,10 +818,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
818 | if (!is_multicast_ether_addr(hdr->addr1) || | 818 | if (!is_multicast_ether_addr(hdr->addr1) || |
819 | ieee80211_is_data(fc) || | 819 | ieee80211_is_data(fc) || |
820 | ieee80211_is_mgmt(fc)) | 820 | ieee80211_is_mgmt(fc)) |
821 | local->dot11TransmittedFragmentCount++; | 821 | I802_DEBUG_INC(local->dot11TransmittedFragmentCount); |
822 | } else { | 822 | } else { |
823 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) | 823 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) |
824 | local->dot11FailedCount++; | 824 | I802_DEBUG_INC(local->dot11FailedCount); |
825 | } | 825 | } |
826 | 826 | ||
827 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) && | 827 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) && |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 4c2e7690226a..6f14591d8ca9 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -69,6 +69,17 @@ | |||
69 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG, \ | 69 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG, \ |
70 | __entry->rx_chains_static, __entry->rx_chains_dynamic | 70 | __entry->rx_chains_static, __entry->rx_chains_dynamic |
71 | 71 | ||
72 | #define KEY_ENTRY __field(u32, cipher) \ | ||
73 | __field(u8, hw_key_idx) \ | ||
74 | __field(u8, flags) \ | ||
75 | __field(s8, keyidx) | ||
76 | #define KEY_ASSIGN(k) __entry->cipher = (k)->cipher; \ | ||
77 | __entry->flags = (k)->flags; \ | ||
78 | __entry->keyidx = (k)->keyidx; \ | ||
79 | __entry->hw_key_idx = (k)->hw_key_idx; | ||
80 | #define KEY_PR_FMT " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d" | ||
81 | #define KEY_PR_ARG __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx | ||
82 | |||
72 | 83 | ||
73 | 84 | ||
74 | /* | 85 | /* |
@@ -522,25 +533,19 @@ TRACE_EVENT(drv_set_key, | |||
522 | LOCAL_ENTRY | 533 | LOCAL_ENTRY |
523 | VIF_ENTRY | 534 | VIF_ENTRY |
524 | STA_ENTRY | 535 | STA_ENTRY |
525 | __field(u32, cipher) | 536 | KEY_ENTRY |
526 | __field(u8, hw_key_idx) | ||
527 | __field(u8, flags) | ||
528 | __field(s8, keyidx) | ||
529 | ), | 537 | ), |
530 | 538 | ||
531 | TP_fast_assign( | 539 | TP_fast_assign( |
532 | LOCAL_ASSIGN; | 540 | LOCAL_ASSIGN; |
533 | VIF_ASSIGN; | 541 | VIF_ASSIGN; |
534 | STA_ASSIGN; | 542 | STA_ASSIGN; |
535 | __entry->cipher = key->cipher; | 543 | KEY_ASSIGN(key); |
536 | __entry->flags = key->flags; | ||
537 | __entry->keyidx = key->keyidx; | ||
538 | __entry->hw_key_idx = key->hw_key_idx; | ||
539 | ), | 544 | ), |
540 | 545 | ||
541 | TP_printk( | 546 | TP_printk( |
542 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, | 547 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT KEY_PR_FMT, |
543 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG | 548 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, KEY_PR_ARG |
544 | ) | 549 | ) |
545 | ); | 550 | ); |
546 | 551 | ||
@@ -656,28 +661,25 @@ TRACE_EVENT(drv_get_stats, | |||
656 | ) | 661 | ) |
657 | ); | 662 | ); |
658 | 663 | ||
659 | TRACE_EVENT(drv_get_tkip_seq, | 664 | TRACE_EVENT(drv_get_key_seq, |
660 | TP_PROTO(struct ieee80211_local *local, | 665 | TP_PROTO(struct ieee80211_local *local, |
661 | u8 hw_key_idx, u32 *iv32, u16 *iv16), | 666 | struct ieee80211_key_conf *key), |
662 | 667 | ||
663 | TP_ARGS(local, hw_key_idx, iv32, iv16), | 668 | TP_ARGS(local, key), |
664 | 669 | ||
665 | TP_STRUCT__entry( | 670 | TP_STRUCT__entry( |
666 | LOCAL_ENTRY | 671 | LOCAL_ENTRY |
667 | __field(u8, hw_key_idx) | 672 | KEY_ENTRY |
668 | __field(u32, iv32) | ||
669 | __field(u16, iv16) | ||
670 | ), | 673 | ), |
671 | 674 | ||
672 | TP_fast_assign( | 675 | TP_fast_assign( |
673 | LOCAL_ASSIGN; | 676 | LOCAL_ASSIGN; |
674 | __entry->hw_key_idx = hw_key_idx; | 677 | KEY_ASSIGN(key); |
675 | __entry->iv32 = *iv32; | ||
676 | __entry->iv16 = *iv16; | ||
677 | ), | 678 | ), |
678 | 679 | ||
679 | TP_printk( | 680 | TP_printk( |
680 | LOCAL_PR_FMT, LOCAL_PR_ARG | 681 | LOCAL_PR_FMT KEY_PR_FMT, |
682 | LOCAL_PR_ARG, KEY_PR_ARG | ||
681 | ) | 683 | ) |
682 | ); | 684 | ); |
683 | 685 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 667111ee6a20..8df134213adf 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -37,6 +37,16 @@ | |||
37 | 37 | ||
38 | /* misc utils */ | 38 | /* misc utils */ |
39 | 39 | ||
40 | static inline void ieee80211_tx_stats(struct net_device *dev, u32 len) | ||
41 | { | ||
42 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); | ||
43 | |||
44 | u64_stats_update_begin(&tstats->syncp); | ||
45 | tstats->tx_packets++; | ||
46 | tstats->tx_bytes += len; | ||
47 | u64_stats_update_end(&tstats->syncp); | ||
48 | } | ||
49 | |||
40 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | 50 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, |
41 | struct sk_buff *skb, int group_addr, | 51 | struct sk_buff *skb, int group_addr, |
42 | int next_frag_len) | 52 | int next_frag_len) |
@@ -987,7 +997,6 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | |||
987 | 997 | ||
988 | skb_queue_walk(&tx->skbs, skb) { | 998 | skb_queue_walk(&tx->skbs, skb) { |
989 | ac = skb_get_queue_mapping(skb); | 999 | ac = skb_get_queue_mapping(skb); |
990 | tx->sta->tx_fragments++; | ||
991 | tx->sta->tx_bytes[ac] += skb->len; | 1000 | tx->sta->tx_bytes[ac] += skb->len; |
992 | } | 1001 | } |
993 | if (ac >= 0) | 1002 | if (ac >= 0) |
@@ -1600,7 +1609,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1600 | if (skb_cloned(skb) && | 1609 | if (skb_cloned(skb) && |
1601 | (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CLONED_SKBS) || | 1610 | (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CLONED_SKBS) || |
1602 | !skb_clone_writable(skb, ETH_HLEN) || | 1611 | !skb_clone_writable(skb, ETH_HLEN) || |
1603 | sdata->crypto_tx_tailroom_needed_cnt)) | 1612 | (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt))) |
1604 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1613 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1605 | else if (head_need || tail_need) | 1614 | else if (head_need || tail_need) |
1606 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1615 | I802_DEBUG_INC(local->tx_expand_skb_head); |
@@ -2387,12 +2396,460 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, | |||
2387 | return ERR_PTR(ret); | 2396 | return ERR_PTR(ret); |
2388 | } | 2397 | } |
2389 | 2398 | ||
2399 | /* | ||
2400 | * fast-xmit overview | ||
2401 | * | ||
2402 | * The core idea of this fast-xmit is to remove per-packet checks by checking | ||
2403 | * them out of band. ieee80211_check_fast_xmit() implements the out-of-band | ||
2404 | * checks that are needed to get the sta->fast_tx pointer assigned, after which | ||
2405 | * much less work can be done per packet. For example, fragmentation must be | ||
2406 | * disabled or the fast_tx pointer will not be set. All the conditions are seen | ||
2407 | * in the code here. | ||
2408 | * | ||
2409 | * Once assigned, the fast_tx data structure also caches the per-packet 802.11 | ||
2410 | * header and other data to aid packet processing in ieee80211_xmit_fast(). | ||
2411 | * | ||
2412 | * The most difficult part of this is that when any of these assumptions | ||
2413 | * change, an external trigger (i.e. a call to ieee80211_clear_fast_xmit(), | ||
2414 | * ieee80211_check_fast_xmit() or friends) is required to reset the data, | ||
2415 | * since the per-packet code no longer checks the conditions. This is reflected | ||
2416 | * by the calls to these functions throughout the rest of the code, and must be | ||
2417 | * maintained if any of the TX path checks change. | ||
2418 | */ | ||
2419 | |||
2420 | void ieee80211_check_fast_xmit(struct sta_info *sta) | ||
2421 | { | ||
2422 | struct ieee80211_fast_tx build = {}, *fast_tx = NULL, *old; | ||
2423 | struct ieee80211_local *local = sta->local; | ||
2424 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
2425 | struct ieee80211_hdr *hdr = (void *)build.hdr; | ||
2426 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
2427 | __le16 fc; | ||
2428 | |||
2429 | if (!(local->hw.flags & IEEE80211_HW_SUPPORT_FAST_XMIT)) | ||
2430 | return; | ||
2431 | |||
2432 | /* Locking here protects both the pointer itself, and against concurrent | ||
2433 | * invocations winning data access races to, e.g., the key pointer that | ||
2434 | * is used. | ||
2435 | * Without it, the invocation of this function right after the key | ||
2436 | * pointer changes wouldn't be sufficient, as another CPU could access | ||
2437 | * the pointer, then stall, and then do the cache update after the CPU | ||
2438 | * that invalidated the key. | ||
2439 | * With the locking, such scenarios cannot happen as the check for the | ||
2440 | * key and the fast-tx assignment are done atomically, so the CPU that | ||
2441 | * modifies the key will either wait or other one will see the key | ||
2442 | * cleared/changed already. | ||
2443 | */ | ||
2444 | spin_lock_bh(&sta->lock); | ||
2445 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS && | ||
2446 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) && | ||
2447 | sdata->vif.type == NL80211_IFTYPE_STATION) | ||
2448 | goto out; | ||
2449 | |||
2450 | if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
2451 | goto out; | ||
2452 | |||
2453 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || | ||
2454 | test_sta_flag(sta, WLAN_STA_PS_DRIVER) || | ||
2455 | test_sta_flag(sta, WLAN_STA_PS_DELIVER)) | ||
2456 | goto out; | ||
2457 | |||
2458 | if (sdata->noack_map) | ||
2459 | goto out; | ||
2460 | |||
2461 | /* fast-xmit doesn't handle fragmentation at all */ | ||
2462 | if (local->hw.wiphy->frag_threshold != (u32)-1 && | ||
2463 | !local->ops->set_frag_threshold) | ||
2464 | goto out; | ||
2465 | |||
2466 | rcu_read_lock(); | ||
2467 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2468 | if (!chanctx_conf) { | ||
2469 | rcu_read_unlock(); | ||
2470 | goto out; | ||
2471 | } | ||
2472 | build.band = chanctx_conf->def.chan->band; | ||
2473 | rcu_read_unlock(); | ||
2474 | |||
2475 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | ||
2476 | |||
2477 | switch (sdata->vif.type) { | ||
2478 | case NL80211_IFTYPE_ADHOC: | ||
2479 | /* DA SA BSSID */ | ||
2480 | build.da_offs = offsetof(struct ieee80211_hdr, addr1); | ||
2481 | build.sa_offs = offsetof(struct ieee80211_hdr, addr2); | ||
2482 | memcpy(hdr->addr3, sdata->u.ibss.bssid, ETH_ALEN); | ||
2483 | build.hdr_len = 24; | ||
2484 | break; | ||
2485 | case NL80211_IFTYPE_STATION: | ||
2486 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
2487 | /* DA SA BSSID */ | ||
2488 | build.da_offs = offsetof(struct ieee80211_hdr, addr1); | ||
2489 | build.sa_offs = offsetof(struct ieee80211_hdr, addr2); | ||
2490 | memcpy(hdr->addr3, sdata->u.mgd.bssid, ETH_ALEN); | ||
2491 | build.hdr_len = 24; | ||
2492 | break; | ||
2493 | } | ||
2494 | |||
2495 | if (sdata->u.mgd.use_4addr) { | ||
2496 | /* non-regular ethertype cannot use the fastpath */ | ||
2497 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | | ||
2498 | IEEE80211_FCTL_TODS); | ||
2499 | /* RA TA DA SA */ | ||
2500 | memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN); | ||
2501 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
2502 | build.da_offs = offsetof(struct ieee80211_hdr, addr3); | ||
2503 | build.sa_offs = offsetof(struct ieee80211_hdr, addr4); | ||
2504 | build.hdr_len = 30; | ||
2505 | break; | ||
2506 | } | ||
2507 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | ||
2508 | /* BSSID SA DA */ | ||
2509 | memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN); | ||
2510 | build.da_offs = offsetof(struct ieee80211_hdr, addr3); | ||
2511 | build.sa_offs = offsetof(struct ieee80211_hdr, addr2); | ||
2512 | build.hdr_len = 24; | ||
2513 | break; | ||
2514 | case NL80211_IFTYPE_AP_VLAN: | ||
2515 | if (sdata->wdev.use_4addr) { | ||
2516 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | | ||
2517 | IEEE80211_FCTL_TODS); | ||
2518 | /* RA TA DA SA */ | ||
2519 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | ||
2520 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
2521 | build.da_offs = offsetof(struct ieee80211_hdr, addr3); | ||
2522 | build.sa_offs = offsetof(struct ieee80211_hdr, addr4); | ||
2523 | build.hdr_len = 30; | ||
2524 | break; | ||
2525 | } | ||
2526 | /* fall through */ | ||
2527 | case NL80211_IFTYPE_AP: | ||
2528 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | ||
2529 | /* DA BSSID SA */ | ||
2530 | build.da_offs = offsetof(struct ieee80211_hdr, addr1); | ||
2531 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
2532 | build.sa_offs = offsetof(struct ieee80211_hdr, addr3); | ||
2533 | build.hdr_len = 24; | ||
2534 | break; | ||
2535 | default: | ||
2536 | /* not handled on fast-xmit */ | ||
2537 | goto out; | ||
2538 | } | ||
2539 | |||
2540 | if (sta->sta.wme) { | ||
2541 | build.hdr_len += 2; | ||
2542 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | ||
2543 | } | ||
2544 | |||
2545 | /* We store the key here so there's no point in using rcu_dereference() | ||
2546 | * but that's fine because the code that changes the pointers will call | ||
2547 | * this function after doing so. For a single CPU that would be enough, | ||
2548 | * for multiple see the comment above. | ||
2549 | */ | ||
2550 | build.key = rcu_access_pointer(sta->ptk[sta->ptk_idx]); | ||
2551 | if (!build.key) | ||
2552 | build.key = rcu_access_pointer(sdata->default_unicast_key); | ||
2553 | if (build.key) { | ||
2554 | bool gen_iv, iv_spc, mmic; | ||
2555 | |||
2556 | gen_iv = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV; | ||
2557 | iv_spc = build.key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE; | ||
2558 | mmic = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
2559 | |||
2560 | /* don't handle software crypto */ | ||
2561 | if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | ||
2562 | goto out; | ||
2563 | |||
2564 | switch (build.key->conf.cipher) { | ||
2565 | case WLAN_CIPHER_SUITE_CCMP: | ||
2566 | case WLAN_CIPHER_SUITE_CCMP_256: | ||
2567 | /* add fixed key ID */ | ||
2568 | if (gen_iv) { | ||
2569 | (build.hdr + build.hdr_len)[3] = | ||
2570 | 0x20 | (build.key->conf.keyidx << 6); | ||
2571 | build.pn_offs = build.hdr_len; | ||
2572 | } | ||
2573 | if (gen_iv || iv_spc) | ||
2574 | build.hdr_len += IEEE80211_CCMP_HDR_LEN; | ||
2575 | break; | ||
2576 | case WLAN_CIPHER_SUITE_GCMP: | ||
2577 | case WLAN_CIPHER_SUITE_GCMP_256: | ||
2578 | /* add fixed key ID */ | ||
2579 | if (gen_iv) { | ||
2580 | (build.hdr + build.hdr_len)[3] = | ||
2581 | 0x20 | (build.key->conf.keyidx << 6); | ||
2582 | build.pn_offs = build.hdr_len; | ||
2583 | } | ||
2584 | if (gen_iv || iv_spc) | ||
2585 | build.hdr_len += IEEE80211_GCMP_HDR_LEN; | ||
2586 | break; | ||
2587 | case WLAN_CIPHER_SUITE_TKIP: | ||
2588 | /* cannot handle MMIC or IV generation in xmit-fast */ | ||
2589 | if (mmic || gen_iv) | ||
2590 | goto out; | ||
2591 | if (iv_spc) | ||
2592 | build.hdr_len += IEEE80211_TKIP_IV_LEN; | ||
2593 | break; | ||
2594 | case WLAN_CIPHER_SUITE_WEP40: | ||
2595 | case WLAN_CIPHER_SUITE_WEP104: | ||
2596 | /* cannot handle IV generation in fast-xmit */ | ||
2597 | if (gen_iv) | ||
2598 | goto out; | ||
2599 | if (iv_spc) | ||
2600 | build.hdr_len += IEEE80211_WEP_IV_LEN; | ||
2601 | break; | ||
2602 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
2603 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: | ||
2604 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: | ||
2605 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: | ||
2606 | WARN(1, | ||
2607 | "management cipher suite 0x%x enabled for data\n", | ||
2608 | build.key->conf.cipher); | ||
2609 | goto out; | ||
2610 | default: | ||
2611 | /* we don't know how to generate IVs for this at all */ | ||
2612 | if (WARN_ON(gen_iv)) | ||
2613 | goto out; | ||
2614 | /* pure hardware keys are OK, of course */ | ||
2615 | if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME)) | ||
2616 | break; | ||
2617 | /* cipher scheme might require space allocation */ | ||
2618 | if (iv_spc && | ||
2619 | build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV) | ||
2620 | goto out; | ||
2621 | if (iv_spc) | ||
2622 | build.hdr_len += build.key->conf.iv_len; | ||
2623 | } | ||
2624 | |||
2625 | fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
2626 | } | ||
2627 | |||
2628 | hdr->frame_control = fc; | ||
2629 | |||
2630 | memcpy(build.hdr + build.hdr_len, | ||
2631 | rfc1042_header, sizeof(rfc1042_header)); | ||
2632 | build.hdr_len += sizeof(rfc1042_header); | ||
2633 | |||
2634 | fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC); | ||
2635 | /* if the kmemdup fails, continue w/o fast_tx */ | ||
2636 | if (!fast_tx) | ||
2637 | goto out; | ||
2638 | |||
2639 | out: | ||
2640 | /* we might have raced against another call to this function */ | ||
2641 | old = rcu_dereference_protected(sta->fast_tx, | ||
2642 | lockdep_is_held(&sta->lock)); | ||
2643 | rcu_assign_pointer(sta->fast_tx, fast_tx); | ||
2644 | if (old) | ||
2645 | kfree_rcu(old, rcu_head); | ||
2646 | spin_unlock_bh(&sta->lock); | ||
2647 | } | ||
2648 | |||
2649 | void ieee80211_check_fast_xmit_all(struct ieee80211_local *local) | ||
2650 | { | ||
2651 | struct sta_info *sta; | ||
2652 | |||
2653 | rcu_read_lock(); | ||
2654 | list_for_each_entry_rcu(sta, &local->sta_list, list) | ||
2655 | ieee80211_check_fast_xmit(sta); | ||
2656 | rcu_read_unlock(); | ||
2657 | } | ||
2658 | |||
2659 | void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata) | ||
2660 | { | ||
2661 | struct ieee80211_local *local = sdata->local; | ||
2662 | struct sta_info *sta; | ||
2663 | |||
2664 | rcu_read_lock(); | ||
2665 | |||
2666 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
2667 | if (sdata != sta->sdata && | ||
2668 | (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) | ||
2669 | continue; | ||
2670 | ieee80211_check_fast_xmit(sta); | ||
2671 | } | ||
2672 | |||
2673 | rcu_read_unlock(); | ||
2674 | } | ||
2675 | |||
2676 | void ieee80211_clear_fast_xmit(struct sta_info *sta) | ||
2677 | { | ||
2678 | struct ieee80211_fast_tx *fast_tx; | ||
2679 | |||
2680 | spin_lock_bh(&sta->lock); | ||
2681 | fast_tx = rcu_dereference_protected(sta->fast_tx, | ||
2682 | lockdep_is_held(&sta->lock)); | ||
2683 | RCU_INIT_POINTER(sta->fast_tx, NULL); | ||
2684 | spin_unlock_bh(&sta->lock); | ||
2685 | |||
2686 | if (fast_tx) | ||
2687 | kfree_rcu(fast_tx, rcu_head); | ||
2688 | } | ||
2689 | |||
2690 | static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, | ||
2691 | struct net_device *dev, struct sta_info *sta, | ||
2692 | struct ieee80211_fast_tx *fast_tx, | ||
2693 | struct sk_buff *skb) | ||
2694 | { | ||
2695 | struct ieee80211_local *local = sdata->local; | ||
2696 | u16 ethertype = (skb->data[12] << 8) | skb->data[13]; | ||
2697 | int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); | ||
2698 | int hw_headroom = sdata->local->hw.extra_tx_headroom; | ||
2699 | struct ethhdr eth; | ||
2700 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2701 | struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; | ||
2702 | struct ieee80211_tx_data tx; | ||
2703 | ieee80211_tx_result r; | ||
2704 | struct tid_ampdu_tx *tid_tx = NULL; | ||
2705 | u8 tid = IEEE80211_NUM_TIDS; | ||
2706 | |||
2707 | /* control port protocol needs a lot of special handling */ | ||
2708 | if (cpu_to_be16(ethertype) == sdata->control_port_protocol) | ||
2709 | return false; | ||
2710 | |||
2711 | /* only RFC 1042 SNAP */ | ||
2712 | if (ethertype < ETH_P_802_3_MIN) | ||
2713 | return false; | ||
2714 | |||
2715 | /* don't handle TX status request here either */ | ||
2716 | if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) | ||
2717 | return false; | ||
2718 | |||
2719 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { | ||
2720 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | ||
2721 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); | ||
2722 | if (tid_tx && | ||
2723 | !test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) | ||
2724 | return false; | ||
2725 | } | ||
2726 | |||
2727 | /* after this point (skb is modified) we cannot return false */ | ||
2728 | |||
2729 | if (skb_shared(skb)) { | ||
2730 | struct sk_buff *tmp_skb = skb; | ||
2731 | |||
2732 | skb = skb_clone(skb, GFP_ATOMIC); | ||
2733 | kfree_skb(tmp_skb); | ||
2734 | |||
2735 | if (!skb) | ||
2736 | return true; | ||
2737 | } | ||
2738 | |||
2739 | ieee80211_tx_stats(dev, skb->len + extra_head); | ||
2740 | |||
2741 | /* will not be crypto-handled beyond what we do here, so use false | ||
2742 | * as the may-encrypt argument for the resize to not account for | ||
2743 | * more room than we already have in 'extra_head' | ||
2744 | */ | ||
2745 | if (unlikely(ieee80211_skb_resize(sdata, skb, | ||
2746 | max_t(int, extra_head + hw_headroom - | ||
2747 | skb_headroom(skb), 0), | ||
2748 | false))) { | ||
2749 | kfree_skb(skb); | ||
2750 | return true; | ||
2751 | } | ||
2752 | |||
2753 | memcpy(ð, skb->data, ETH_HLEN - 2); | ||
2754 | hdr = (void *)skb_push(skb, extra_head); | ||
2755 | memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len); | ||
2756 | memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN); | ||
2757 | memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN); | ||
2758 | |||
2759 | memset(info, 0, sizeof(*info)); | ||
2760 | info->band = fast_tx->band; | ||
2761 | info->control.vif = &sdata->vif; | ||
2762 | info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT | | ||
2763 | IEEE80211_TX_CTL_DONTFRAG | | ||
2764 | (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0); | ||
2765 | |||
2766 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { | ||
2767 | *ieee80211_get_qos_ctl(hdr) = tid; | ||
2768 | hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid); | ||
2769 | } else { | ||
2770 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | ||
2771 | hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number); | ||
2772 | sdata->sequence_number += 0x10; | ||
2773 | } | ||
2774 | |||
2775 | sta->tx_msdu[tid]++; | ||
2776 | |||
2777 | info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; | ||
2778 | |||
2779 | __skb_queue_head_init(&tx.skbs); | ||
2780 | |||
2781 | tx.flags = IEEE80211_TX_UNICAST; | ||
2782 | tx.local = local; | ||
2783 | tx.sdata = sdata; | ||
2784 | tx.sta = sta; | ||
2785 | tx.key = fast_tx->key; | ||
2786 | |||
2787 | if (fast_tx->key) | ||
2788 | info->control.hw_key = &fast_tx->key->conf; | ||
2789 | |||
2790 | if (!(local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) { | ||
2791 | tx.skb = skb; | ||
2792 | r = ieee80211_tx_h_rate_ctrl(&tx); | ||
2793 | skb = tx.skb; | ||
2794 | tx.skb = NULL; | ||
2795 | |||
2796 | if (r != TX_CONTINUE) { | ||
2797 | if (r != TX_QUEUED) | ||
2798 | kfree_skb(skb); | ||
2799 | return true; | ||
2800 | } | ||
2801 | } | ||
2802 | |||
2803 | /* statistics normally done by ieee80211_tx_h_stats (but that | ||
2804 | * has to consider fragmentation, so is more complex) | ||
2805 | */ | ||
2806 | sta->tx_bytes[skb_get_queue_mapping(skb)] += skb->len; | ||
2807 | sta->tx_packets[skb_get_queue_mapping(skb)]++; | ||
2808 | |||
2809 | if (fast_tx->pn_offs) { | ||
2810 | u64 pn; | ||
2811 | u8 *crypto_hdr = skb->data + fast_tx->pn_offs; | ||
2812 | |||
2813 | switch (fast_tx->key->conf.cipher) { | ||
2814 | case WLAN_CIPHER_SUITE_CCMP: | ||
2815 | case WLAN_CIPHER_SUITE_CCMP_256: | ||
2816 | pn = atomic64_inc_return(&fast_tx->key->u.ccmp.tx_pn); | ||
2817 | crypto_hdr[0] = pn; | ||
2818 | crypto_hdr[1] = pn >> 8; | ||
2819 | crypto_hdr[4] = pn >> 16; | ||
2820 | crypto_hdr[5] = pn >> 24; | ||
2821 | crypto_hdr[6] = pn >> 32; | ||
2822 | crypto_hdr[7] = pn >> 40; | ||
2823 | break; | ||
2824 | case WLAN_CIPHER_SUITE_GCMP: | ||
2825 | case WLAN_CIPHER_SUITE_GCMP_256: | ||
2826 | pn = atomic64_inc_return(&fast_tx->key->u.gcmp.tx_pn); | ||
2827 | crypto_hdr[0] = pn; | ||
2828 | crypto_hdr[1] = pn >> 8; | ||
2829 | crypto_hdr[4] = pn >> 16; | ||
2830 | crypto_hdr[5] = pn >> 24; | ||
2831 | crypto_hdr[6] = pn >> 32; | ||
2832 | crypto_hdr[7] = pn >> 40; | ||
2833 | break; | ||
2834 | } | ||
2835 | } | ||
2836 | |||
2837 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
2838 | sdata = container_of(sdata->bss, | ||
2839 | struct ieee80211_sub_if_data, u.ap); | ||
2840 | |||
2841 | __skb_queue_tail(&tx.skbs, skb); | ||
2842 | ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false); | ||
2843 | return true; | ||
2844 | } | ||
2845 | |||
2390 | void __ieee80211_subif_start_xmit(struct sk_buff *skb, | 2846 | void __ieee80211_subif_start_xmit(struct sk_buff *skb, |
2391 | struct net_device *dev, | 2847 | struct net_device *dev, |
2392 | u32 info_flags) | 2848 | u32 info_flags) |
2393 | { | 2849 | { |
2394 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2850 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2395 | struct sta_info *sta; | 2851 | struct sta_info *sta; |
2852 | struct sk_buff *next; | ||
2396 | 2853 | ||
2397 | if (unlikely(skb->len < ETH_HLEN)) { | 2854 | if (unlikely(skb->len < ETH_HLEN)) { |
2398 | kfree_skb(skb); | 2855 | kfree_skb(skb); |
@@ -2401,20 +2858,67 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2401 | 2858 | ||
2402 | rcu_read_lock(); | 2859 | rcu_read_lock(); |
2403 | 2860 | ||
2404 | if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { | 2861 | if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) |
2405 | kfree_skb(skb); | 2862 | goto out_free; |
2406 | goto out; | 2863 | |
2864 | if (!IS_ERR_OR_NULL(sta)) { | ||
2865 | struct ieee80211_fast_tx *fast_tx; | ||
2866 | |||
2867 | fast_tx = rcu_dereference(sta->fast_tx); | ||
2868 | |||
2869 | if (fast_tx && | ||
2870 | ieee80211_xmit_fast(sdata, dev, sta, fast_tx, skb)) | ||
2871 | goto out; | ||
2407 | } | 2872 | } |
2408 | 2873 | ||
2409 | skb = ieee80211_build_hdr(sdata, skb, info_flags, sta); | 2874 | if (skb_is_gso(skb)) { |
2410 | if (IS_ERR(skb)) | 2875 | struct sk_buff *segs; |
2411 | goto out; | 2876 | |
2877 | segs = skb_gso_segment(skb, 0); | ||
2878 | if (IS_ERR(segs)) { | ||
2879 | goto out_free; | ||
2880 | } else if (segs) { | ||
2881 | consume_skb(skb); | ||
2882 | skb = segs; | ||
2883 | } | ||
2884 | } else { | ||
2885 | /* we cannot process non-linear frames on this path */ | ||
2886 | if (skb_linearize(skb)) { | ||
2887 | kfree_skb(skb); | ||
2888 | goto out; | ||
2889 | } | ||
2890 | |||
2891 | /* the frame could be fragmented, software-encrypted, and other | ||
2892 | * things so we cannot really handle checksum offload with it - | ||
2893 | * fix it up in software before we handle anything else. | ||
2894 | */ | ||
2895 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | ||
2896 | skb_set_transport_header(skb, | ||
2897 | skb_checksum_start_offset(skb)); | ||
2898 | if (skb_checksum_help(skb)) | ||
2899 | goto out_free; | ||
2900 | } | ||
2901 | } | ||
2902 | |||
2903 | next = skb; | ||
2904 | while (next) { | ||
2905 | skb = next; | ||
2906 | next = skb->next; | ||
2412 | 2907 | ||
2413 | dev->stats.tx_packets++; | 2908 | skb->prev = NULL; |
2414 | dev->stats.tx_bytes += skb->len; | 2909 | skb->next = NULL; |
2415 | dev->trans_start = jiffies; | 2910 | |
2911 | skb = ieee80211_build_hdr(sdata, skb, info_flags, sta); | ||
2912 | if (IS_ERR(skb)) | ||
2913 | goto out; | ||
2416 | 2914 | ||
2417 | ieee80211_xmit(sdata, sta, skb); | 2915 | ieee80211_tx_stats(dev, skb->len); |
2916 | |||
2917 | ieee80211_xmit(sdata, sta, skb); | ||
2918 | } | ||
2919 | goto out; | ||
2920 | out_free: | ||
2921 | kfree_skb(skb); | ||
2418 | out: | 2922 | out: |
2419 | rcu_read_unlock(); | 2923 | rcu_read_unlock(); |
2420 | } | 2924 | } |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 7aaf7415dc4c..915b328b9ac5 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -698,19 +698,20 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, | |||
698 | EXPORT_SYMBOL(cfg80211_chandef_usable); | 698 | EXPORT_SYMBOL(cfg80211_chandef_usable); |
699 | 699 | ||
700 | /* | 700 | /* |
701 | * For GO only, check if the channel can be used under permissive conditions | 701 | * Check if the channel can be used under permissive conditions mandated by |
702 | * mandated by the some regulatory bodies, i.e., the channel is marked with | 702 | * some regulatory bodies, i.e., the channel is marked with |
703 | * IEEE80211_CHAN_GO_CONCURRENT and there is an additional station interface | 703 | * IEEE80211_CHAN_IR_CONCURRENT and there is an additional station interface |
704 | * associated to an AP on the same channel or on the same UNII band | 704 | * associated to an AP on the same channel or on the same UNII band |
705 | * (assuming that the AP is an authorized master). | 705 | * (assuming that the AP is an authorized master). |
706 | * In addition allow the GO to operate on a channel on which indoor operation is | 706 | * In addition allow operation on a channel on which indoor operation is |
707 | * allowed, iff we are currently operating in an indoor environment. | 707 | * allowed, iff we are currently operating in an indoor environment. |
708 | */ | 708 | */ |
709 | static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev, | 709 | static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, |
710 | enum nl80211_iftype iftype, | ||
710 | struct ieee80211_channel *chan) | 711 | struct ieee80211_channel *chan) |
711 | { | 712 | { |
712 | struct wireless_dev *wdev_iter; | 713 | struct wireless_dev *wdev; |
713 | struct wiphy *wiphy = wiphy_idx_to_wiphy(rdev->wiphy_idx); | 714 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
714 | 715 | ||
715 | ASSERT_RTNL(); | 716 | ASSERT_RTNL(); |
716 | 717 | ||
@@ -718,32 +719,48 @@ static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev, | |||
718 | !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)) | 719 | !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)) |
719 | return false; | 720 | return false; |
720 | 721 | ||
722 | /* only valid for GO and TDLS off-channel (station/p2p-CL) */ | ||
723 | if (iftype != NL80211_IFTYPE_P2P_GO && | ||
724 | iftype != NL80211_IFTYPE_STATION && | ||
725 | iftype != NL80211_IFTYPE_P2P_CLIENT) | ||
726 | return false; | ||
727 | |||
721 | if (regulatory_indoor_allowed() && | 728 | if (regulatory_indoor_allowed() && |
722 | (chan->flags & IEEE80211_CHAN_INDOOR_ONLY)) | 729 | (chan->flags & IEEE80211_CHAN_INDOOR_ONLY)) |
723 | return true; | 730 | return true; |
724 | 731 | ||
725 | if (!(chan->flags & IEEE80211_CHAN_GO_CONCURRENT)) | 732 | if (!(chan->flags & IEEE80211_CHAN_IR_CONCURRENT)) |
726 | return false; | 733 | return false; |
727 | 734 | ||
728 | /* | 735 | /* |
729 | * Generally, it is possible to rely on another device/driver to allow | 736 | * Generally, it is possible to rely on another device/driver to allow |
730 | * the GO concurrent relaxation, however, since the device can further | 737 | * the IR concurrent relaxation, however, since the device can further |
731 | * enforce the relaxation (by doing a similar verifications as this), | 738 | * enforce the relaxation (by doing a similar verifications as this), |
732 | * and thus fail the GO instantiation, consider only the interfaces of | 739 | * and thus fail the GO instantiation, consider only the interfaces of |
733 | * the current registered device. | 740 | * the current registered device. |
734 | */ | 741 | */ |
735 | list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { | 742 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
736 | struct ieee80211_channel *other_chan = NULL; | 743 | struct ieee80211_channel *other_chan = NULL; |
737 | int r1, r2; | 744 | int r1, r2; |
738 | 745 | ||
739 | if (wdev_iter->iftype != NL80211_IFTYPE_STATION || | 746 | wdev_lock(wdev); |
740 | !netif_running(wdev_iter->netdev)) | 747 | if (wdev->iftype == NL80211_IFTYPE_STATION && |
741 | continue; | 748 | wdev->current_bss) |
742 | 749 | other_chan = wdev->current_bss->pub.channel; | |
743 | wdev_lock(wdev_iter); | 750 | |
744 | if (wdev_iter->current_bss) | 751 | /* |
745 | other_chan = wdev_iter->current_bss->pub.channel; | 752 | * If a GO already operates on the same GO_CONCURRENT channel, |
746 | wdev_unlock(wdev_iter); | 753 | * this one (maybe the same one) can beacon as well. We allow |
754 | * the operation even if the station we relied on with | ||
755 | * GO_CONCURRENT is disconnected now. But then we must make sure | ||
756 | * we're not outdoor on an indoor-only channel. | ||
757 | */ | ||
758 | if (iftype == NL80211_IFTYPE_P2P_GO && | ||
759 | wdev->iftype == NL80211_IFTYPE_P2P_GO && | ||
760 | wdev->beacon_interval && | ||
761 | !(chan->flags & IEEE80211_CHAN_INDOOR_ONLY)) | ||
762 | other_chan = wdev->chandef.chan; | ||
763 | wdev_unlock(wdev); | ||
747 | 764 | ||
748 | if (!other_chan) | 765 | if (!other_chan) |
749 | continue; | 766 | continue; |
@@ -784,7 +801,6 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
784 | struct cfg80211_chan_def *chandef, | 801 | struct cfg80211_chan_def *chandef, |
785 | enum nl80211_iftype iftype) | 802 | enum nl80211_iftype iftype) |
786 | { | 803 | { |
787 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | ||
788 | bool res; | 804 | bool res; |
789 | u32 prohibited_flags = IEEE80211_CHAN_DISABLED | | 805 | u32 prohibited_flags = IEEE80211_CHAN_DISABLED | |
790 | IEEE80211_CHAN_RADAR; | 806 | IEEE80211_CHAN_RADAR; |
@@ -792,13 +808,12 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
792 | trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype); | 808 | trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype); |
793 | 809 | ||
794 | /* | 810 | /* |
795 | * Under certain conditions suggested by the some regulatory bodies | 811 | * Under certain conditions suggested by some regulatory bodies a |
796 | * a GO can operate on channels marked with IEEE80211_NO_IR | 812 | * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag |
797 | * so set this flag only if such relaxations are not enabled and | 813 | * only if such relaxations are not enabled and the conditions are not |
798 | * the conditions are not met. | 814 | * met. |
799 | */ | 815 | */ |
800 | if (iftype != NL80211_IFTYPE_P2P_GO || | 816 | if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan)) |
801 | !cfg80211_go_permissive_chan(rdev, chandef->chan)) | ||
802 | prohibited_flags |= IEEE80211_CHAN_NO_IR; | 817 | prohibited_flags |= IEEE80211_CHAN_NO_IR; |
803 | 818 | ||
804 | if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && | 819 | if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index dd78445c7d50..c264effd00a6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -639,8 +639,8 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
639 | if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) && | 639 | if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) && |
640 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY)) | 640 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY)) |
641 | goto nla_put_failure; | 641 | goto nla_put_failure; |
642 | if ((chan->flags & IEEE80211_CHAN_GO_CONCURRENT) && | 642 | if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) && |
643 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_GO_CONCURRENT)) | 643 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT)) |
644 | goto nla_put_failure; | 644 | goto nla_put_failure; |
645 | if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) && | 645 | if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) && |
646 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ)) | 646 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ)) |
@@ -4061,7 +4061,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
4061 | return -EINVAL; | 4061 | return -EINVAL; |
4062 | break; | 4062 | break; |
4063 | case CFG80211_STA_MESH_PEER_USER: | 4063 | case CFG80211_STA_MESH_PEER_USER: |
4064 | if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) | 4064 | if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION && |
4065 | params->plink_action != NL80211_PLINK_ACTION_BLOCK) | ||
4065 | return -EINVAL; | 4066 | return -EINVAL; |
4066 | break; | 4067 | break; |
4067 | } | 4068 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 0e347f888fe9..d359e0610198 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -989,8 +989,8 @@ static u32 map_regdom_flags(u32 rd_flags) | |||
989 | channel_flags |= IEEE80211_CHAN_NO_OFDM; | 989 | channel_flags |= IEEE80211_CHAN_NO_OFDM; |
990 | if (rd_flags & NL80211_RRF_NO_OUTDOOR) | 990 | if (rd_flags & NL80211_RRF_NO_OUTDOOR) |
991 | channel_flags |= IEEE80211_CHAN_INDOOR_ONLY; | 991 | channel_flags |= IEEE80211_CHAN_INDOOR_ONLY; |
992 | if (rd_flags & NL80211_RRF_GO_CONCURRENT) | 992 | if (rd_flags & NL80211_RRF_IR_CONCURRENT) |
993 | channel_flags |= IEEE80211_CHAN_GO_CONCURRENT; | 993 | channel_flags |= IEEE80211_CHAN_IR_CONCURRENT; |
994 | if (rd_flags & NL80211_RRF_NO_HT40MINUS) | 994 | if (rd_flags & NL80211_RRF_NO_HT40MINUS) |
995 | channel_flags |= IEEE80211_CHAN_NO_HT40MINUS; | 995 | channel_flags |= IEEE80211_CHAN_NO_HT40MINUS; |
996 | if (rd_flags & NL80211_RRF_NO_HT40PLUS) | 996 | if (rd_flags & NL80211_RRF_NO_HT40PLUS) |