diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-04-10 10:39:27 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-10 10:39:27 -0400 |
commit | d3641409a05dcb8e28116bb2ad638f5a42805d9d (patch) | |
tree | 1d43a5e0129709502edb631a4fd66de369ee5620 /net/mac80211 | |
parent | 953c96e0d85615d1ab1f100e525d376053294dc2 (diff) | |
parent | 6fe5468f452c0c40348ebd4e737758a842286ca8 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/rt2x00/rt2x00pci.c
net/mac80211/sta_info.c
net/wireless/core.h
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 29 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.c | 10 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 22 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 60 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 11 | ||||
-rw-r--r-- | net/mac80211/iface.c | 17 | ||||
-rw-r--r-- | net/mac80211/key.c | 129 | ||||
-rw-r--r-- | net/mac80211/key.h | 15 | ||||
-rw-r--r-- | net/mac80211/main.c | 22 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 5 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 12 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 8 | ||||
-rw-r--r-- | net/mac80211/pm.c | 6 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 24 | ||||
-rw-r--r-- | net/mac80211/scan.c | 7 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 54 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 9 | ||||
-rw-r--r-- | net/mac80211/trace.h | 35 | ||||
-rw-r--r-- | net/mac80211/tx.c | 8 | ||||
-rw-r--r-- | net/mac80211/util.c | 48 |
20 files changed, 314 insertions, 217 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c34e6d78a592..c50c19402588 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -175,7 +175,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
175 | * add it to the device after the station. | 175 | * add it to the device after the station. |
176 | */ | 176 | */ |
177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { | 177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { |
178 | ieee80211_key_free(sdata->local, key); | 178 | ieee80211_key_free_unused(key); |
179 | err = -ENOENT; | 179 | err = -ENOENT; |
180 | goto out_unlock; | 180 | goto out_unlock; |
181 | } | 181 | } |
@@ -214,8 +214,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
214 | } | 214 | } |
215 | 215 | ||
216 | err = ieee80211_key_link(key, sdata, sta); | 216 | err = ieee80211_key_link(key, sdata, sta); |
217 | if (err) | ||
218 | ieee80211_key_free(sdata->local, key); | ||
219 | 217 | ||
220 | out_unlock: | 218 | out_unlock: |
221 | mutex_unlock(&sdata->local->sta_mtx); | 219 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -254,7 +252,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
254 | goto out_unlock; | 252 | goto out_unlock; |
255 | } | 253 | } |
256 | 254 | ||
257 | __ieee80211_key_free(key, true); | 255 | ieee80211_key_free(key, true); |
258 | 256 | ||
259 | ret = 0; | 257 | ret = 0; |
260 | out_unlock: | 258 | out_unlock: |
@@ -445,12 +443,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
445 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 443 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
446 | struct ieee80211_local *local = sdata->local; | 444 | struct ieee80211_local *local = sdata->local; |
447 | struct timespec uptime; | 445 | struct timespec uptime; |
446 | u64 packets = 0; | ||
447 | int ac; | ||
448 | 448 | ||
449 | sinfo->generation = sdata->local->sta_generation; | 449 | sinfo->generation = sdata->local->sta_generation; |
450 | 450 | ||
451 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 451 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
452 | STATION_INFO_RX_BYTES | | 452 | STATION_INFO_RX_BYTES64 | |
453 | STATION_INFO_TX_BYTES | | 453 | STATION_INFO_TX_BYTES64 | |
454 | STATION_INFO_RX_PACKETS | | 454 | STATION_INFO_RX_PACKETS | |
455 | STATION_INFO_TX_PACKETS | | 455 | STATION_INFO_TX_PACKETS | |
456 | STATION_INFO_TX_RETRIES | | 456 | STATION_INFO_TX_RETRIES | |
@@ -467,10 +467,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
467 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 467 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
468 | 468 | ||
469 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 469 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
470 | sinfo->tx_bytes = 0; | ||
471 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
472 | sinfo->tx_bytes += sta->tx_bytes[ac]; | ||
473 | packets += sta->tx_packets[ac]; | ||
474 | } | ||
475 | sinfo->tx_packets = packets; | ||
470 | sinfo->rx_bytes = sta->rx_bytes; | 476 | sinfo->rx_bytes = sta->rx_bytes; |
471 | sinfo->tx_bytes = sta->tx_bytes; | ||
472 | sinfo->rx_packets = sta->rx_packets; | 477 | sinfo->rx_packets = sta->rx_packets; |
473 | sinfo->tx_packets = sta->tx_packets; | ||
474 | sinfo->tx_retries = sta->tx_retry_count; | 478 | sinfo->tx_retries = sta->tx_retry_count; |
475 | sinfo->tx_failed = sta->tx_retry_failed; | 479 | sinfo->tx_failed = sta->tx_retry_failed; |
476 | sinfo->rx_dropped_misc = sta->rx_dropped; | 480 | sinfo->rx_dropped_misc = sta->rx_dropped; |
@@ -598,8 +602,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
598 | data[i++] += sta->rx_fragments; \ | 602 | data[i++] += sta->rx_fragments; \ |
599 | data[i++] += sta->rx_dropped; \ | 603 | data[i++] += sta->rx_dropped; \ |
600 | \ | 604 | \ |
601 | data[i++] += sta->tx_packets; \ | 605 | data[i++] += sinfo.tx_packets; \ |
602 | data[i++] += sta->tx_bytes; \ | 606 | data[i++] += sinfo.tx_bytes; \ |
603 | data[i++] += sta->tx_fragments; \ | 607 | data[i++] += sta->tx_fragments; \ |
604 | data[i++] += sta->tx_filtered_count; \ | 608 | data[i++] += sta->tx_filtered_count; \ |
605 | data[i++] += sta->tx_retry_failed; \ | 609 | data[i++] += sta->tx_retry_failed; \ |
@@ -621,13 +625,14 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
621 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) | 625 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) |
622 | goto do_survey; | 626 | goto do_survey; |
623 | 627 | ||
628 | sinfo.filled = 0; | ||
629 | sta_set_sinfo(sta, &sinfo); | ||
630 | |||
624 | i = 0; | 631 | i = 0; |
625 | ADD_STA_STATS(sta); | 632 | ADD_STA_STATS(sta); |
626 | 633 | ||
627 | data[i++] = sta->sta_state; | 634 | data[i++] = sta->sta_state; |
628 | 635 | ||
629 | sinfo.filled = 0; | ||
630 | sta_set_sinfo(sta, &sinfo); | ||
631 | 636 | ||
632 | if (sinfo.filled & STATION_INFO_TX_BITRATE) | 637 | if (sinfo.filled & STATION_INFO_TX_BITRATE) |
633 | data[i] = 100000 * | 638 | data[i] = 100000 * |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index c3a3082b72e5..1521cabad3d6 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -295,7 +295,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
295 | char buf[50]; | 295 | char buf[50]; |
296 | struct ieee80211_key *key; | 296 | struct ieee80211_key *key; |
297 | 297 | ||
298 | if (!sdata->debugfs.dir) | 298 | if (!sdata->vif.debugfs_dir) |
299 | return; | 299 | return; |
300 | 300 | ||
301 | lockdep_assert_held(&sdata->local->key_mtx); | 301 | lockdep_assert_held(&sdata->local->key_mtx); |
@@ -311,7 +311,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
311 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 311 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
312 | sdata->debugfs.default_unicast_key = | 312 | sdata->debugfs.default_unicast_key = |
313 | debugfs_create_symlink("default_unicast_key", | 313 | debugfs_create_symlink("default_unicast_key", |
314 | sdata->debugfs.dir, buf); | 314 | sdata->vif.debugfs_dir, buf); |
315 | } | 315 | } |
316 | 316 | ||
317 | if (sdata->debugfs.default_multicast_key) { | 317 | if (sdata->debugfs.default_multicast_key) { |
@@ -325,7 +325,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
325 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 325 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
326 | sdata->debugfs.default_multicast_key = | 326 | sdata->debugfs.default_multicast_key = |
327 | debugfs_create_symlink("default_multicast_key", | 327 | debugfs_create_symlink("default_multicast_key", |
328 | sdata->debugfs.dir, buf); | 328 | sdata->vif.debugfs_dir, buf); |
329 | } | 329 | } |
330 | } | 330 | } |
331 | 331 | ||
@@ -334,7 +334,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | |||
334 | char buf[50]; | 334 | char buf[50]; |
335 | struct ieee80211_key *key; | 335 | struct ieee80211_key *key; |
336 | 336 | ||
337 | if (!sdata->debugfs.dir) | 337 | if (!sdata->vif.debugfs_dir) |
338 | return; | 338 | return; |
339 | 339 | ||
340 | key = key_mtx_dereference(sdata->local, | 340 | key = key_mtx_dereference(sdata->local, |
@@ -343,7 +343,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | |||
343 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 343 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
344 | sdata->debugfs.default_mgmt_key = | 344 | sdata->debugfs.default_mgmt_key = |
345 | debugfs_create_symlink("default_mgmt_key", | 345 | debugfs_create_symlink("default_mgmt_key", |
346 | sdata->debugfs.dir, buf); | 346 | sdata->vif.debugfs_dir, buf); |
347 | } else | 347 | } else |
348 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 348 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
349 | } | 349 | } |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 059bbb82e84f..ddb426867904 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -521,7 +521,7 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, | |||
521 | #endif | 521 | #endif |
522 | 522 | ||
523 | #define DEBUGFS_ADD_MODE(name, mode) \ | 523 | #define DEBUGFS_ADD_MODE(name, mode) \ |
524 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | 524 | debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \ |
525 | sdata, &name##_ops); | 525 | sdata, &name##_ops); |
526 | 526 | ||
527 | #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) | 527 | #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) |
@@ -577,7 +577,7 @@ static void add_mesh_files(struct ieee80211_sub_if_data *sdata) | |||
577 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | 577 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) |
578 | { | 578 | { |
579 | struct dentry *dir = debugfs_create_dir("mesh_stats", | 579 | struct dentry *dir = debugfs_create_dir("mesh_stats", |
580 | sdata->debugfs.dir); | 580 | sdata->vif.debugfs_dir); |
581 | #define MESHSTATS_ADD(name)\ | 581 | #define MESHSTATS_ADD(name)\ |
582 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); | 582 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); |
583 | 583 | ||
@@ -594,7 +594,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | |||
594 | static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | 594 | static void add_mesh_config(struct ieee80211_sub_if_data *sdata) |
595 | { | 595 | { |
596 | struct dentry *dir = debugfs_create_dir("mesh_config", | 596 | struct dentry *dir = debugfs_create_dir("mesh_config", |
597 | sdata->debugfs.dir); | 597 | sdata->vif.debugfs_dir); |
598 | 598 | ||
599 | #define MESHPARAMS_ADD(name) \ | 599 | #define MESHPARAMS_ADD(name) \ |
600 | debugfs_create_file(#name, 0600, dir, sdata, &name##_ops); | 600 | debugfs_create_file(#name, 0600, dir, sdata, &name##_ops); |
@@ -631,7 +631,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
631 | 631 | ||
632 | static void add_files(struct ieee80211_sub_if_data *sdata) | 632 | static void add_files(struct ieee80211_sub_if_data *sdata) |
633 | { | 633 | { |
634 | if (!sdata->debugfs.dir) | 634 | if (!sdata->vif.debugfs_dir) |
635 | return; | 635 | return; |
636 | 636 | ||
637 | DEBUGFS_ADD(flags); | 637 | DEBUGFS_ADD(flags); |
@@ -673,21 +673,21 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | |||
673 | char buf[10+IFNAMSIZ]; | 673 | char buf[10+IFNAMSIZ]; |
674 | 674 | ||
675 | sprintf(buf, "netdev:%s", sdata->name); | 675 | sprintf(buf, "netdev:%s", sdata->name); |
676 | sdata->debugfs.dir = debugfs_create_dir(buf, | 676 | sdata->vif.debugfs_dir = debugfs_create_dir(buf, |
677 | sdata->local->hw.wiphy->debugfsdir); | 677 | sdata->local->hw.wiphy->debugfsdir); |
678 | if (sdata->debugfs.dir) | 678 | if (sdata->vif.debugfs_dir) |
679 | sdata->debugfs.subdir_stations = debugfs_create_dir("stations", | 679 | sdata->debugfs.subdir_stations = debugfs_create_dir("stations", |
680 | sdata->debugfs.dir); | 680 | sdata->vif.debugfs_dir); |
681 | add_files(sdata); | 681 | add_files(sdata); |
682 | } | 682 | } |
683 | 683 | ||
684 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | 684 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) |
685 | { | 685 | { |
686 | if (!sdata->debugfs.dir) | 686 | if (!sdata->vif.debugfs_dir) |
687 | return; | 687 | return; |
688 | 688 | ||
689 | debugfs_remove_recursive(sdata->debugfs.dir); | 689 | debugfs_remove_recursive(sdata->vif.debugfs_dir); |
690 | sdata->debugfs.dir = NULL; | 690 | sdata->vif.debugfs_dir = NULL; |
691 | } | 691 | } |
692 | 692 | ||
693 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | 693 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
@@ -695,7 +695,7 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | |||
695 | struct dentry *dir; | 695 | struct dentry *dir; |
696 | char buf[10 + IFNAMSIZ]; | 696 | char buf[10 + IFNAMSIZ]; |
697 | 697 | ||
698 | dir = sdata->debugfs.dir; | 698 | dir = sdata->vif.debugfs_dir; |
699 | 699 | ||
700 | if (!dir) | 700 | if (!dir) |
701 | return; | 701 | return; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 832acea4a5cb..169664c122e2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -241,6 +241,22 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | |||
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | 243 | ||
244 | static inline void drv_set_multicast_list(struct ieee80211_local *local, | ||
245 | struct ieee80211_sub_if_data *sdata, | ||
246 | struct netdev_hw_addr_list *mc_list) | ||
247 | { | ||
248 | bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
249 | |||
250 | trace_drv_set_multicast_list(local, sdata, mc_list->count); | ||
251 | |||
252 | check_sdata_in_driver(sdata); | ||
253 | |||
254 | if (local->ops->set_multicast_list) | ||
255 | local->ops->set_multicast_list(&local->hw, &sdata->vif, | ||
256 | allmulti, mc_list); | ||
257 | trace_drv_return_void(local); | ||
258 | } | ||
259 | |||
244 | static inline void drv_configure_filter(struct ieee80211_local *local, | 260 | static inline void drv_configure_filter(struct ieee80211_local *local, |
245 | unsigned int changed_flags, | 261 | unsigned int changed_flags, |
246 | unsigned int *total_flags, | 262 | unsigned int *total_flags, |
@@ -531,43 +547,6 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, | |||
531 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, | 547 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, |
532 | sta, dir); | 548 | sta, dir); |
533 | } | 549 | } |
534 | |||
535 | static inline | ||
536 | void drv_add_interface_debugfs(struct ieee80211_local *local, | ||
537 | struct ieee80211_sub_if_data *sdata) | ||
538 | { | ||
539 | might_sleep(); | ||
540 | |||
541 | check_sdata_in_driver(sdata); | ||
542 | |||
543 | if (!local->ops->add_interface_debugfs) | ||
544 | return; | ||
545 | |||
546 | local->ops->add_interface_debugfs(&local->hw, &sdata->vif, | ||
547 | sdata->debugfs.dir); | ||
548 | } | ||
549 | |||
550 | static inline | ||
551 | void drv_remove_interface_debugfs(struct ieee80211_local *local, | ||
552 | struct ieee80211_sub_if_data *sdata) | ||
553 | { | ||
554 | might_sleep(); | ||
555 | |||
556 | check_sdata_in_driver(sdata); | ||
557 | |||
558 | if (!local->ops->remove_interface_debugfs) | ||
559 | return; | ||
560 | |||
561 | local->ops->remove_interface_debugfs(&local->hw, &sdata->vif, | ||
562 | sdata->debugfs.dir); | ||
563 | } | ||
564 | #else | ||
565 | static inline | ||
566 | void drv_add_interface_debugfs(struct ieee80211_local *local, | ||
567 | struct ieee80211_sub_if_data *sdata) {} | ||
568 | static inline | ||
569 | void drv_remove_interface_debugfs(struct ieee80211_local *local, | ||
570 | struct ieee80211_sub_if_data *sdata) {} | ||
571 | #endif | 550 | #endif |
572 | 551 | ||
573 | static inline __must_check | 552 | static inline __must_check |
@@ -741,13 +720,14 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local) | |||
741 | local->ops->rfkill_poll(&local->hw); | 720 | local->ops->rfkill_poll(&local->hw); |
742 | } | 721 | } |
743 | 722 | ||
744 | static inline void drv_flush(struct ieee80211_local *local, bool drop) | 723 | static inline void drv_flush(struct ieee80211_local *local, |
724 | u32 queues, bool drop) | ||
745 | { | 725 | { |
746 | might_sleep(); | 726 | might_sleep(); |
747 | 727 | ||
748 | trace_drv_flush(local, drop); | 728 | trace_drv_flush(local, queues, drop); |
749 | if (local->ops->flush) | 729 | if (local->ops->flush) |
750 | local->ops->flush(&local->hw, drop); | 730 | local->ops->flush(&local->hw, queues, drop); |
751 | trace_drv_return_void(local); | 731 | trace_drv_return_void(local); |
752 | } | 732 | } |
753 | 733 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e140184c28ce..0b09716d22ad 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -759,7 +759,6 @@ struct ieee80211_sub_if_data { | |||
759 | 759 | ||
760 | #ifdef CONFIG_MAC80211_DEBUGFS | 760 | #ifdef CONFIG_MAC80211_DEBUGFS |
761 | struct { | 761 | struct { |
762 | struct dentry *dir; | ||
763 | struct dentry *subdir_stations; | 762 | struct dentry *subdir_stations; |
764 | struct dentry *default_unicast_key; | 763 | struct dentry *default_unicast_key; |
765 | struct dentry *default_multicast_key; | 764 | struct dentry *default_multicast_key; |
@@ -801,11 +800,6 @@ enum sdata_queue_type { | |||
801 | enum { | 800 | enum { |
802 | IEEE80211_RX_MSG = 1, | 801 | IEEE80211_RX_MSG = 1, |
803 | IEEE80211_TX_STATUS_MSG = 2, | 802 | IEEE80211_TX_STATUS_MSG = 2, |
804 | IEEE80211_EOSP_MSG = 3, | ||
805 | }; | ||
806 | |||
807 | struct skb_eosp_msg_data { | ||
808 | u8 sta[ETH_ALEN], iface[ETH_ALEN]; | ||
809 | }; | 803 | }; |
810 | 804 | ||
811 | enum queue_stop_reason { | 805 | enum queue_stop_reason { |
@@ -816,6 +810,7 @@ enum queue_stop_reason { | |||
816 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 810 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
817 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 811 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
818 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, | 812 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, |
813 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | ||
819 | }; | 814 | }; |
820 | 815 | ||
821 | #ifdef CONFIG_MAC80211_LEDS | 816 | #ifdef CONFIG_MAC80211_LEDS |
@@ -1530,8 +1525,10 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | |||
1530 | struct ieee80211_hdr *hdr, bool ack); | 1525 | struct ieee80211_hdr *hdr, bool ack); |
1531 | 1526 | ||
1532 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1527 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1528 | unsigned long queues, | ||
1533 | enum queue_stop_reason reason); | 1529 | enum queue_stop_reason reason); |
1534 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 1530 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
1531 | unsigned long queues, | ||
1535 | enum queue_stop_reason reason); | 1532 | enum queue_stop_reason reason); |
1536 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1533 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1537 | enum queue_stop_reason reason); | 1534 | enum queue_stop_reason reason); |
@@ -1548,6 +1545,8 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
1548 | { | 1545 | { |
1549 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | 1546 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); |
1550 | } | 1547 | } |
1548 | void ieee80211_flush_queues(struct ieee80211_local *local, | ||
1549 | struct ieee80211_sub_if_data *sdata); | ||
1551 | 1550 | ||
1552 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1551 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1553 | u16 transaction, u16 auth_alg, u16 status, | 1552 | u16 transaction, u16 auth_alg, u16 status, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a2b5e17036bb..69aaba79a9f7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -92,7 +92,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
92 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | 92 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) |
93 | return 0; | 93 | return 0; |
94 | 94 | ||
95 | drv_flush(local, false); | 95 | ieee80211_flush_queues(local, NULL); |
96 | 96 | ||
97 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 97 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
98 | return IEEE80211_CONF_CHANGE_IDLE; | 98 | return IEEE80211_CONF_CHANGE_IDLE; |
@@ -560,8 +560,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
560 | goto err_del_interface; | 560 | goto err_del_interface; |
561 | } | 561 | } |
562 | 562 | ||
563 | drv_add_interface_debugfs(local, sdata); | ||
564 | |||
565 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 563 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
566 | local->fif_pspoll++; | 564 | local->fif_pspoll++; |
567 | local->fif_probe_req++; | 565 | local->fif_probe_req++; |
@@ -849,8 +847,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
849 | case NL80211_IFTYPE_AP: | 847 | case NL80211_IFTYPE_AP: |
850 | skb_queue_purge(&sdata->skb_queue); | 848 | skb_queue_purge(&sdata->skb_queue); |
851 | 849 | ||
852 | drv_remove_interface_debugfs(local, sdata); | ||
853 | |||
854 | if (going_down) | 850 | if (going_down) |
855 | drv_remove_interface(local, sdata); | 851 | drv_remove_interface(local, sdata); |
856 | } | 852 | } |
@@ -922,6 +918,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
922 | atomic_dec(&local->iff_promiscs); | 918 | atomic_dec(&local->iff_promiscs); |
923 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 919 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
924 | } | 920 | } |
921 | |||
922 | /* | ||
923 | * TODO: If somebody needs this on AP interfaces, | ||
924 | * it can be enabled easily but multicast | ||
925 | * addresses from VLANs need to be synced. | ||
926 | */ | ||
927 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
928 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
929 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
930 | drv_set_multicast_list(local, sdata, &dev->mc); | ||
931 | |||
925 | spin_lock_bh(&local->filter_lock); | 932 | spin_lock_bh(&local->filter_lock); |
926 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 933 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
927 | spin_unlock_bh(&local->filter_lock); | 934 | spin_unlock_bh(&local->filter_lock); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 99e9f6ae6a54..67059b88fea5 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -248,11 +248,11 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | |||
248 | } | 248 | } |
249 | 249 | ||
250 | 250 | ||
251 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | 251 | static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, |
252 | struct sta_info *sta, | 252 | struct sta_info *sta, |
253 | bool pairwise, | 253 | bool pairwise, |
254 | struct ieee80211_key *old, | 254 | struct ieee80211_key *old, |
255 | struct ieee80211_key *new) | 255 | struct ieee80211_key *new) |
256 | { | 256 | { |
257 | int idx; | 257 | int idx; |
258 | bool defunikey, defmultikey, defmgmtkey; | 258 | bool defunikey, defmultikey, defmgmtkey; |
@@ -397,25 +397,21 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
397 | return key; | 397 | return key; |
398 | } | 398 | } |
399 | 399 | ||
400 | static void ieee80211_key_free_common(struct ieee80211_key *key) | ||
401 | { | ||
402 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) | ||
403 | ieee80211_aes_key_free(key->u.ccmp.tfm); | ||
404 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | ||
405 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | ||
406 | kfree(key); | ||
407 | } | ||
408 | |||
400 | static void __ieee80211_key_destroy(struct ieee80211_key *key, | 409 | static void __ieee80211_key_destroy(struct ieee80211_key *key, |
401 | bool delay_tailroom) | 410 | bool delay_tailroom) |
402 | { | 411 | { |
403 | if (!key) | ||
404 | return; | ||
405 | |||
406 | /* | ||
407 | * Synchronize so the TX path can no longer be using | ||
408 | * this key before we free/remove it. | ||
409 | */ | ||
410 | synchronize_net(); | ||
411 | |||
412 | if (key->local) | 412 | if (key->local) |
413 | ieee80211_key_disable_hw_accel(key); | 413 | ieee80211_key_disable_hw_accel(key); |
414 | 414 | ||
415 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) | ||
416 | ieee80211_aes_key_free(key->u.ccmp.tfm); | ||
417 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | ||
418 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | ||
419 | if (key->local) { | 415 | if (key->local) { |
420 | struct ieee80211_sub_if_data *sdata = key->sdata; | 416 | struct ieee80211_sub_if_data *sdata = key->sdata; |
421 | 417 | ||
@@ -431,7 +427,28 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key, | |||
431 | } | 427 | } |
432 | } | 428 | } |
433 | 429 | ||
434 | kfree(key); | 430 | ieee80211_key_free_common(key); |
431 | } | ||
432 | |||
433 | static void ieee80211_key_destroy(struct ieee80211_key *key, | ||
434 | bool delay_tailroom) | ||
435 | { | ||
436 | if (!key) | ||
437 | return; | ||
438 | |||
439 | /* | ||
440 | * Synchronize so the TX path can no longer be using | ||
441 | * this key before we free/remove it. | ||
442 | */ | ||
443 | synchronize_net(); | ||
444 | |||
445 | __ieee80211_key_destroy(key, delay_tailroom); | ||
446 | } | ||
447 | |||
448 | void ieee80211_key_free_unused(struct ieee80211_key *key) | ||
449 | { | ||
450 | WARN_ON(key->sdata || key->local); | ||
451 | ieee80211_key_free_common(key); | ||
435 | } | 452 | } |
436 | 453 | ||
437 | int ieee80211_key_link(struct ieee80211_key *key, | 454 | int ieee80211_key_link(struct ieee80211_key *key, |
@@ -462,19 +479,22 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
462 | 479 | ||
463 | increment_tailroom_need_count(sdata); | 480 | increment_tailroom_need_count(sdata); |
464 | 481 | ||
465 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); | 482 | ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
466 | __ieee80211_key_destroy(old_key, true); | 483 | ieee80211_key_destroy(old_key, true); |
467 | 484 | ||
468 | ieee80211_debugfs_key_add(key); | 485 | ieee80211_debugfs_key_add(key); |
469 | 486 | ||
470 | ret = ieee80211_key_enable_hw_accel(key); | 487 | ret = ieee80211_key_enable_hw_accel(key); |
471 | 488 | ||
489 | if (ret) | ||
490 | ieee80211_key_free(key, true); | ||
491 | |||
472 | mutex_unlock(&sdata->local->key_mtx); | 492 | mutex_unlock(&sdata->local->key_mtx); |
473 | 493 | ||
474 | return ret; | 494 | return ret; |
475 | } | 495 | } |
476 | 496 | ||
477 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) | 497 | void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) |
478 | { | 498 | { |
479 | if (!key) | 499 | if (!key) |
480 | return; | 500 | return; |
@@ -483,18 +503,10 @@ void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) | |||
483 | * Replace key with nothingness if it was ever used. | 503 | * Replace key with nothingness if it was ever used. |
484 | */ | 504 | */ |
485 | if (key->sdata) | 505 | if (key->sdata) |
486 | __ieee80211_key_replace(key->sdata, key->sta, | 506 | ieee80211_key_replace(key->sdata, key->sta, |
487 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 507 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
488 | key, NULL); | 508 | key, NULL); |
489 | __ieee80211_key_destroy(key, delay_tailroom); | 509 | ieee80211_key_destroy(key, delay_tailroom); |
490 | } | ||
491 | |||
492 | void ieee80211_key_free(struct ieee80211_local *local, | ||
493 | struct ieee80211_key *key) | ||
494 | { | ||
495 | mutex_lock(&local->key_mtx); | ||
496 | __ieee80211_key_free(key, true); | ||
497 | mutex_unlock(&local->key_mtx); | ||
498 | } | 510 | } |
499 | 511 | ||
500 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | 512 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) |
@@ -554,6 +566,7 @@ EXPORT_SYMBOL(ieee80211_iter_keys); | |||
554 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 566 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) |
555 | { | 567 | { |
556 | struct ieee80211_key *key, *tmp; | 568 | struct ieee80211_key *key, *tmp; |
569 | LIST_HEAD(keys); | ||
557 | 570 | ||
558 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); | 571 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); |
559 | 572 | ||
@@ -565,17 +578,65 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
565 | 578 | ||
566 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 579 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
567 | 580 | ||
568 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 581 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) { |
569 | __ieee80211_key_free(key, false); | 582 | ieee80211_key_replace(key->sdata, key->sta, |
583 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | ||
584 | key, NULL); | ||
585 | list_add_tail(&key->list, &keys); | ||
586 | } | ||
570 | 587 | ||
571 | ieee80211_debugfs_key_update_default(sdata); | 588 | ieee80211_debugfs_key_update_default(sdata); |
572 | 589 | ||
590 | if (!list_empty(&keys)) { | ||
591 | synchronize_net(); | ||
592 | list_for_each_entry_safe(key, tmp, &keys, list) | ||
593 | __ieee80211_key_destroy(key, false); | ||
594 | } | ||
595 | |||
573 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | 596 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || |
574 | sdata->crypto_tx_tailroom_pending_dec); | 597 | sdata->crypto_tx_tailroom_pending_dec); |
575 | 598 | ||
576 | mutex_unlock(&sdata->local->key_mtx); | 599 | mutex_unlock(&sdata->local->key_mtx); |
577 | } | 600 | } |
578 | 601 | ||
602 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | ||
603 | struct sta_info *sta) | ||
604 | { | ||
605 | struct ieee80211_key *key, *tmp; | ||
606 | LIST_HEAD(keys); | ||
607 | int i; | ||
608 | |||
609 | mutex_lock(&local->key_mtx); | ||
610 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
611 | key = key_mtx_dereference(local, sta->gtk[i]); | ||
612 | if (!key) | ||
613 | continue; | ||
614 | ieee80211_key_replace(key->sdata, key->sta, | ||
615 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | ||
616 | key, NULL); | ||
617 | list_add(&key->list, &keys); | ||
618 | } | ||
619 | |||
620 | key = key_mtx_dereference(local, sta->ptk); | ||
621 | if (key) { | ||
622 | ieee80211_key_replace(key->sdata, key->sta, | ||
623 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | ||
624 | key, NULL); | ||
625 | list_add(&key->list, &keys); | ||
626 | } | ||
627 | |||
628 | /* | ||
629 | * NB: the station code relies on this being | ||
630 | * done even if there aren't any keys | ||
631 | */ | ||
632 | synchronize_net(); | ||
633 | |||
634 | list_for_each_entry_safe(key, tmp, &keys, list) | ||
635 | __ieee80211_key_destroy(key, true); | ||
636 | |||
637 | mutex_unlock(&local->key_mtx); | ||
638 | } | ||
639 | |||
579 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk) | 640 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk) |
580 | { | 641 | { |
581 | struct ieee80211_sub_if_data *sdata; | 642 | struct ieee80211_sub_if_data *sdata; |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 2a682d81cee9..e8de3e6d7804 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -129,19 +129,20 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
129 | size_t seq_len, const u8 *seq); | 129 | size_t seq_len, const u8 *seq); |
130 | /* | 130 | /* |
131 | * Insert a key into data structures (sdata, sta if necessary) | 131 | * Insert a key into data structures (sdata, sta if necessary) |
132 | * to make it used, free old key. | 132 | * to make it used, free old key. On failure, also free the new key. |
133 | */ | 133 | */ |
134 | int __must_check ieee80211_key_link(struct ieee80211_key *key, | 134 | int ieee80211_key_link(struct ieee80211_key *key, |
135 | struct ieee80211_sub_if_data *sdata, | 135 | struct ieee80211_sub_if_data *sdata, |
136 | struct sta_info *sta); | 136 | struct sta_info *sta); |
137 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); | 137 | void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); |
138 | void ieee80211_key_free(struct ieee80211_local *local, | 138 | void ieee80211_key_free_unused(struct ieee80211_key *key); |
139 | struct ieee80211_key *key); | ||
140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, | 139 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
141 | bool uni, bool multi); | 140 | bool uni, bool multi); |
142 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 141 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
143 | int idx); | 142 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 143 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
144 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | ||
145 | struct sta_info *sta); | ||
145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 146 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
146 | 147 | ||
147 | #define key_mtx_dereference(local, ref) \ | 148 | #define key_mtx_dereference(local, ref) \ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5a53aa5ede80..c6f81ecc36a1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -100,7 +100,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | 102 | u32 offchannel_flag; |
103 | bool scanning = false; | ||
104 | 103 | ||
105 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 104 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
106 | if (local->scan_channel) { | 105 | if (local->scan_channel) { |
@@ -147,9 +146,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
147 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 146 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
148 | } | 147 | } |
149 | 148 | ||
150 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || | ||
151 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
152 | test_bit(SCAN_HW_SCANNING, &local->scanning); | ||
153 | power = chan->max_power; | 149 | power = chan->max_power; |
154 | 150 | ||
155 | rcu_read_lock(); | 151 | rcu_read_lock(); |
@@ -226,8 +222,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | |||
226 | static void ieee80211_tasklet_handler(unsigned long data) | 222 | static void ieee80211_tasklet_handler(unsigned long data) |
227 | { | 223 | { |
228 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 224 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
229 | struct sta_info *sta, *tmp; | ||
230 | struct skb_eosp_msg_data *eosp_data; | ||
231 | struct sk_buff *skb; | 225 | struct sk_buff *skb; |
232 | 226 | ||
233 | while ((skb = skb_dequeue(&local->skb_queue)) || | 227 | while ((skb = skb_dequeue(&local->skb_queue)) || |
@@ -243,18 +237,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
243 | skb->pkt_type = 0; | 237 | skb->pkt_type = 0; |
244 | ieee80211_tx_status(&local->hw, skb); | 238 | ieee80211_tx_status(&local->hw, skb); |
245 | break; | 239 | break; |
246 | case IEEE80211_EOSP_MSG: | ||
247 | eosp_data = (void *)skb->cb; | ||
248 | for_each_sta_info(local, eosp_data->sta, sta, tmp) { | ||
249 | /* skip wrong virtual interface */ | ||
250 | if (memcmp(eosp_data->iface, | ||
251 | sta->sdata->vif.addr, ETH_ALEN)) | ||
252 | continue; | ||
253 | clear_sta_flag(sta, WLAN_STA_SP); | ||
254 | break; | ||
255 | } | ||
256 | dev_kfree_skb(skb); | ||
257 | break; | ||
258 | default: | 240 | default: |
259 | WARN(1, "mac80211: Packet is of unknown type %d\n", | 241 | WARN(1, "mac80211: Packet is of unknown type %d\n", |
260 | skb->pkt_type); | 242 | skb->pkt_type); |
@@ -295,8 +277,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
295 | "Hardware restart was requested\n"); | 277 | "Hardware restart was requested\n"); |
296 | 278 | ||
297 | /* use this reason, ieee80211_reconfig will unblock it */ | 279 | /* use this reason, ieee80211_reconfig will unblock it */ |
298 | ieee80211_stop_queues_by_reason(hw, | 280 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
299 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 281 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
300 | 282 | ||
301 | /* | 283 | /* |
302 | * Stop all Rx during the reconfig. We don't want state changes | 284 | * Stop all Rx during the reconfig. We don't want state changes |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 77b5710db241..123a300cef57 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -699,10 +699,8 @@ out_free: | |||
699 | static int | 699 | static int |
700 | ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh) | 700 | ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh) |
701 | { | 701 | { |
702 | struct ieee80211_sub_if_data *sdata; | ||
703 | struct beacon_data *old_bcn; | 702 | struct beacon_data *old_bcn; |
704 | int ret; | 703 | int ret; |
705 | sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh); | ||
706 | 704 | ||
707 | mutex_lock(&ifmsh->mtx); | 705 | mutex_lock(&ifmsh->mtx); |
708 | 706 | ||
@@ -833,9 +831,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, | |||
833 | struct ieee80211_mgmt *hdr; | 831 | struct ieee80211_mgmt *hdr; |
834 | struct ieee802_11_elems elems; | 832 | struct ieee802_11_elems elems; |
835 | size_t baselen; | 833 | size_t baselen; |
836 | u8 *pos, *end; | 834 | u8 *pos; |
837 | 835 | ||
838 | end = ((u8 *) mgmt) + len; | ||
839 | pos = mgmt->u.probe_req.variable; | 836 | pos = mgmt->u.probe_req.variable; |
840 | baselen = (u8 *) pos - (u8 *) mgmt; | 837 | baselen = (u8 *) pos - (u8 *) mgmt; |
841 | if (baselen > len) | 838 | if (baselen > len) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 167158646593..e06dbbf8cb4c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1009,6 +1009,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
1009 | 1009 | ||
1010 | /* XXX: wait for a beacon first? */ | 1010 | /* XXX: wait for a beacon first? */ |
1011 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 1011 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
1012 | IEEE80211_MAX_QUEUE_MAP, | ||
1012 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1013 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1013 | out: | 1014 | out: |
1014 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 1015 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
@@ -1108,6 +1109,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1108 | 1109 | ||
1109 | if (sw_elem->mode) | 1110 | if (sw_elem->mode) |
1110 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 1111 | ieee80211_stop_queues_by_reason(&sdata->local->hw, |
1112 | IEEE80211_MAX_QUEUE_MAP, | ||
1111 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1113 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1112 | 1114 | ||
1113 | if (sdata->local->ops->channel_switch) { | 1115 | if (sdata->local->ops->channel_switch) { |
@@ -1375,6 +1377,7 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work) | |||
1375 | } | 1377 | } |
1376 | 1378 | ||
1377 | ieee80211_wake_queues_by_reason(&local->hw, | 1379 | ieee80211_wake_queues_by_reason(&local->hw, |
1380 | IEEE80211_MAX_QUEUE_MAP, | ||
1378 | IEEE80211_QUEUE_STOP_REASON_PS); | 1381 | IEEE80211_QUEUE_STOP_REASON_PS); |
1379 | } | 1382 | } |
1380 | 1383 | ||
@@ -1436,7 +1439,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
1436 | else { | 1439 | else { |
1437 | ieee80211_send_nullfunc(local, sdata, 1); | 1440 | ieee80211_send_nullfunc(local, sdata, 1); |
1438 | /* Flush to get the tx status of nullfunc frame */ | 1441 | /* Flush to get the tx status of nullfunc frame */ |
1439 | drv_flush(local, false); | 1442 | ieee80211_flush_queues(local, sdata); |
1440 | } | 1443 | } |
1441 | } | 1444 | } |
1442 | 1445 | ||
@@ -1767,7 +1770,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1767 | 1770 | ||
1768 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | 1771 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ |
1769 | if (tx) | 1772 | if (tx) |
1770 | drv_flush(local, false); | 1773 | ieee80211_flush_queues(local, sdata); |
1771 | 1774 | ||
1772 | /* deauthenticate/disassociate now */ | 1775 | /* deauthenticate/disassociate now */ |
1773 | if (tx || frame_buf) | 1776 | if (tx || frame_buf) |
@@ -1776,7 +1779,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1776 | 1779 | ||
1777 | /* flush out frame */ | 1780 | /* flush out frame */ |
1778 | if (tx) | 1781 | if (tx) |
1779 | drv_flush(local, false); | 1782 | ieee80211_flush_queues(local, sdata); |
1780 | 1783 | ||
1781 | /* clear bssid only after building the needed mgmt frames */ | 1784 | /* clear bssid only after building the needed mgmt frames */ |
1782 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1785 | memset(ifmgd->bssid, 0, ETH_ALEN); |
@@ -1948,7 +1951,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1948 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1951 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
1949 | run_again(ifmgd, ifmgd->probe_timeout); | 1952 | run_again(ifmgd, ifmgd->probe_timeout); |
1950 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 1953 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
1951 | drv_flush(sdata->local, false); | 1954 | ieee80211_flush_queues(sdata->local, sdata); |
1952 | } | 1955 | } |
1953 | 1956 | ||
1954 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | 1957 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
@@ -2071,6 +2074,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
2071 | true, frame_buf); | 2074 | true, frame_buf); |
2072 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 2075 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
2073 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 2076 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
2077 | IEEE80211_MAX_QUEUE_MAP, | ||
2074 | IEEE80211_QUEUE_STOP_REASON_CSA); | 2078 | IEEE80211_QUEUE_STOP_REASON_CSA); |
2075 | mutex_unlock(&ifmgd->mtx); | 2079 | mutex_unlock(&ifmgd->mtx); |
2076 | 2080 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 950c95bec13d..cce795871ab1 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -118,9 +118,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) | |||
118 | * Stop queues and transmit all frames queued by the driver | 118 | * Stop queues and transmit all frames queued by the driver |
119 | * before sending nullfunc to enable powersave at the AP. | 119 | * before sending nullfunc to enable powersave at the AP. |
120 | */ | 120 | */ |
121 | ieee80211_stop_queues_by_reason(&local->hw, | 121 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | 122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); |
123 | drv_flush(local, false); | 123 | ieee80211_flush_queues(local, NULL); |
124 | 124 | ||
125 | mutex_lock(&local->iflist_mtx); | 125 | mutex_lock(&local->iflist_mtx); |
126 | list_for_each_entry(sdata, &local->interfaces, list) { | 126 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -181,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) | |||
181 | } | 181 | } |
182 | mutex_unlock(&local->iflist_mtx); | 182 | mutex_unlock(&local->iflist_mtx); |
183 | 183 | ||
184 | ieee80211_wake_queues_by_reason(&local->hw, | 184 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
185 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | 185 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); |
186 | } | 186 | } |
187 | 187 | ||
@@ -382,7 +382,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
382 | ieee80211_roc_notify_destroy(roc, !roc->abort); | 382 | ieee80211_roc_notify_destroy(roc, !roc->abort); |
383 | 383 | ||
384 | if (started) { | 384 | if (started) { |
385 | drv_flush(local, false); | 385 | ieee80211_flush_queues(local, NULL); |
386 | 386 | ||
387 | local->tmp_channel = NULL; | 387 | local->tmp_channel = NULL; |
388 | ieee80211_hw_config(local, 0); | 388 | ieee80211_hw_config(local, 0); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index b471a67f224d..3d16f4e61743 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -30,12 +30,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
30 | } | 30 | } |
31 | 31 | ||
32 | ieee80211_stop_queues_by_reason(hw, | 32 | ieee80211_stop_queues_by_reason(hw, |
33 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 33 | IEEE80211_MAX_QUEUE_MAP, |
34 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | ||
34 | 35 | ||
35 | /* flush out all packets */ | 36 | /* flush out all packets */ |
36 | synchronize_net(); | 37 | synchronize_net(); |
37 | 38 | ||
38 | drv_flush(local, false); | 39 | ieee80211_flush_queues(local, NULL); |
39 | 40 | ||
40 | local->quiescing = true; | 41 | local->quiescing = true; |
41 | /* make quiescing visible to timers everywhere */ | 42 | /* make quiescing visible to timers everywhere */ |
@@ -68,6 +69,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
68 | mutex_unlock(&local->sta_mtx); | 69 | mutex_unlock(&local->sta_mtx); |
69 | } | 70 | } |
70 | ieee80211_wake_queues_by_reason(hw, | 71 | ieee80211_wake_queues_by_reason(hw, |
72 | IEEE80211_MAX_QUEUE_MAP, | ||
71 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 73 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
72 | return err; | 74 | return err; |
73 | } else if (err > 0) { | 75 | } else if (err > 0) { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 749552bdcfe1..d2b264d1311d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -202,14 +202,23 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | |||
202 | struct minstrel_rate_stats *mr; | 202 | struct minstrel_rate_stats *mr; |
203 | unsigned int nsecs = 0; | 203 | unsigned int nsecs = 0; |
204 | unsigned int tp; | 204 | unsigned int tp; |
205 | unsigned int prob; | ||
205 | 206 | ||
206 | mr = &mi->groups[group].rates[rate]; | 207 | mr = &mi->groups[group].rates[rate]; |
208 | prob = mr->probability; | ||
207 | 209 | ||
208 | if (mr->probability < MINSTREL_FRAC(1, 10)) { | 210 | if (prob < MINSTREL_FRAC(1, 10)) { |
209 | mr->cur_tp = 0; | 211 | mr->cur_tp = 0; |
210 | return; | 212 | return; |
211 | } | 213 | } |
212 | 214 | ||
215 | /* | ||
216 | * For the throughput calculation, limit the probability value to 90% to | ||
217 | * account for collision related packet error rate fluctuation | ||
218 | */ | ||
219 | if (prob > MINSTREL_FRAC(9, 10)) | ||
220 | prob = MINSTREL_FRAC(9, 10); | ||
221 | |||
213 | if (group != MINSTREL_CCK_GROUP) | 222 | if (group != MINSTREL_CCK_GROUP) |
214 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); | 223 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); |
215 | 224 | ||
@@ -639,15 +648,18 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
639 | /* | 648 | /* |
640 | * Sampling might add some overhead (RTS, no aggregation) | 649 | * Sampling might add some overhead (RTS, no aggregation) |
641 | * to the frame. Hence, don't use sampling for the currently | 650 | * to the frame. Hence, don't use sampling for the currently |
642 | * used max TP rate. | 651 | * used rates. |
643 | */ | 652 | */ |
644 | if (sample_idx == mi->max_tp_rate) | 653 | if (sample_idx == mi->max_tp_rate || |
654 | sample_idx == mi->max_tp_rate2 || | ||
655 | sample_idx == mi->max_prob_rate) | ||
645 | return -1; | 656 | return -1; |
657 | |||
646 | /* | 658 | /* |
647 | * When not using MRR, do not sample if the probability is already | 659 | * Do not sample if the probability is already higher than 95% |
648 | * higher than 95% to avoid wasting airtime | 660 | * to avoid wasting airtime. |
649 | */ | 661 | */ |
650 | if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100))) | 662 | if (mr->probability > MINSTREL_FRAC(95, 100)) |
651 | return -1; | 663 | return -1; |
652 | 664 | ||
653 | /* | 665 | /* |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 43a45cf00e06..cb34cbbaa20c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -153,7 +153,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
153 | u8 *elements; | 153 | u8 *elements; |
154 | struct ieee80211_channel *channel; | 154 | struct ieee80211_channel *channel; |
155 | size_t baselen; | 155 | size_t baselen; |
156 | bool beacon; | ||
157 | struct ieee802_11_elems elems; | 156 | struct ieee802_11_elems elems; |
158 | 157 | ||
159 | if (skb->len < 24 || | 158 | if (skb->len < 24 || |
@@ -175,11 +174,9 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
175 | 174 | ||
176 | elements = mgmt->u.probe_resp.variable; | 175 | elements = mgmt->u.probe_resp.variable; |
177 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | 176 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); |
178 | beacon = false; | ||
179 | } else { | 177 | } else { |
180 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); | 178 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); |
181 | elements = mgmt->u.beacon.variable; | 179 | elements = mgmt->u.beacon.variable; |
182 | beacon = true; | ||
183 | } | 180 | } |
184 | 181 | ||
185 | if (baselen > skb->len) | 182 | if (baselen > skb->len) |
@@ -335,7 +332,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
335 | ieee80211_offchannel_stop_vifs(local); | 332 | ieee80211_offchannel_stop_vifs(local); |
336 | 333 | ||
337 | /* ensure nullfunc is transmitted before leaving operating channel */ | 334 | /* ensure nullfunc is transmitted before leaving operating channel */ |
338 | drv_flush(local, false); | 335 | ieee80211_flush_queues(local, NULL); |
339 | 336 | ||
340 | ieee80211_configure_filter(local); | 337 | ieee80211_configure_filter(local); |
341 | 338 | ||
@@ -671,7 +668,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local, | |||
671 | ieee80211_offchannel_stop_vifs(local); | 668 | ieee80211_offchannel_stop_vifs(local); |
672 | 669 | ||
673 | if (local->ops->flush) { | 670 | if (local->ops->flush) { |
674 | drv_flush(local, false); | 671 | ieee80211_flush_queues(local, NULL); |
675 | *next_delay = 0; | 672 | *next_delay = 0; |
676 | } else | 673 | } else |
677 | *next_delay = HZ / 10; | 674 | *next_delay = HZ / 10; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 85458a28ffa0..11216bc13b27 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -556,6 +556,15 @@ static inline void __bss_tim_clear(u8 *tim, u16 id) | |||
556 | tim[id / 8] &= ~(1 << (id % 8)); | 556 | tim[id / 8] &= ~(1 << (id % 8)); |
557 | } | 557 | } |
558 | 558 | ||
559 | static inline bool __bss_tim_get(u8 *tim, u16 id) | ||
560 | { | ||
561 | /* | ||
562 | * This format has been mandated by the IEEE specifications, | ||
563 | * so this line may not be changed to use the test_bit() format. | ||
564 | */ | ||
565 | return tim[id / 8] & (1 << (id % 8)); | ||
566 | } | ||
567 | |||
559 | static unsigned long ieee80211_tids_for_ac(int ac) | 568 | static unsigned long ieee80211_tids_for_ac(int ac) |
560 | { | 569 | { |
561 | /* If we ever support TIDs > 7, this obviously needs to be adjusted */ | 570 | /* If we ever support TIDs > 7, this obviously needs to be adjusted */ |
@@ -636,6 +645,9 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
636 | done: | 645 | done: |
637 | spin_lock_bh(&local->tim_lock); | 646 | spin_lock_bh(&local->tim_lock); |
638 | 647 | ||
648 | if (indicate_tim == __bss_tim_get(ps->tim, id)) | ||
649 | goto out_unlock; | ||
650 | |||
639 | if (indicate_tim) | 651 | if (indicate_tim) |
640 | __bss_tim_set(ps->tim, id); | 652 | __bss_tim_set(ps->tim, id); |
641 | else | 653 | else |
@@ -647,6 +659,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
647 | local->tim_in_locked_section = false; | 659 | local->tim_in_locked_section = false; |
648 | } | 660 | } |
649 | 661 | ||
662 | out_unlock: | ||
650 | spin_unlock_bh(&local->tim_lock); | 663 | spin_unlock_bh(&local->tim_lock); |
651 | } | 664 | } |
652 | 665 | ||
@@ -770,8 +783,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
770 | { | 783 | { |
771 | struct ieee80211_local *local; | 784 | struct ieee80211_local *local; |
772 | struct ieee80211_sub_if_data *sdata; | 785 | struct ieee80211_sub_if_data *sdata; |
773 | int ret, i; | 786 | int ret; |
774 | bool have_key = false; | ||
775 | 787 | ||
776 | might_sleep(); | 788 | might_sleep(); |
777 | 789 | ||
@@ -798,22 +810,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
798 | 810 | ||
799 | list_del_rcu(&sta->list); | 811 | list_del_rcu(&sta->list); |
800 | 812 | ||
801 | mutex_lock(&local->key_mtx); | 813 | /* this always calls synchronize_net() */ |
802 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | 814 | ieee80211_free_sta_keys(local, sta); |
803 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), | ||
804 | true); | ||
805 | have_key = true; | ||
806 | } | ||
807 | if (sta->ptk) { | ||
808 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), | ||
809 | true); | ||
810 | have_key = true; | ||
811 | } | ||
812 | |||
813 | mutex_unlock(&local->key_mtx); | ||
814 | |||
815 | if (!have_key) | ||
816 | synchronize_net(); | ||
817 | 815 | ||
818 | sta->dead = true; | 816 | sta->dead = true; |
819 | 817 | ||
@@ -1399,30 +1397,16 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
1399 | } | 1397 | } |
1400 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 1398 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
1401 | 1399 | ||
1402 | void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta) | 1400 | void ieee80211_sta_eosp(struct ieee80211_sta *pubsta) |
1403 | { | 1401 | { |
1404 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 1402 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
1405 | struct ieee80211_local *local = sta->local; | 1403 | struct ieee80211_local *local = sta->local; |
1406 | struct sk_buff *skb; | ||
1407 | struct skb_eosp_msg_data *data; | ||
1408 | 1404 | ||
1409 | trace_api_eosp(local, pubsta); | 1405 | trace_api_eosp(local, pubsta); |
1410 | 1406 | ||
1411 | skb = alloc_skb(0, GFP_ATOMIC); | 1407 | clear_sta_flag(sta, WLAN_STA_SP); |
1412 | if (!skb) { | ||
1413 | /* too bad ... but race is better than loss */ | ||
1414 | clear_sta_flag(sta, WLAN_STA_SP); | ||
1415 | return; | ||
1416 | } | ||
1417 | |||
1418 | data = (void *)skb->cb; | ||
1419 | memcpy(data->sta, pubsta->addr, ETH_ALEN); | ||
1420 | memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN); | ||
1421 | skb->pkt_type = IEEE80211_EOSP_MSG; | ||
1422 | skb_queue_tail(&local->skb_queue, skb); | ||
1423 | tasklet_schedule(&local->tasklet); | ||
1424 | } | 1408 | } |
1425 | EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe); | 1409 | EXPORT_SYMBOL(ieee80211_sta_eosp); |
1426 | 1410 | ||
1427 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | 1411 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, |
1428 | u8 tid, bool buffered) | 1412 | u8 tid, bool buffered) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index e5868c32d1a3..adc30045f99e 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -333,7 +333,8 @@ struct sta_info { | |||
333 | unsigned long driver_buffered_tids; | 333 | unsigned long driver_buffered_tids; |
334 | 334 | ||
335 | /* Updated from RX path only, no locking requirements */ | 335 | /* Updated from RX path only, no locking requirements */ |
336 | unsigned long rx_packets, rx_bytes; | 336 | unsigned long rx_packets; |
337 | u64 rx_bytes; | ||
337 | unsigned long wep_weak_iv_count; | 338 | unsigned long wep_weak_iv_count; |
338 | unsigned long last_rx; | 339 | unsigned long last_rx; |
339 | long last_connected; | 340 | long last_connected; |
@@ -353,9 +354,9 @@ struct sta_info { | |||
353 | unsigned int fail_avg; | 354 | unsigned int fail_avg; |
354 | 355 | ||
355 | /* Updated from TX path only, no locking requirements */ | 356 | /* Updated from TX path only, no locking requirements */ |
356 | unsigned long tx_packets; | 357 | u32 tx_fragments; |
357 | unsigned long tx_bytes; | 358 | u64 tx_packets[IEEE80211_NUM_ACS]; |
358 | unsigned long tx_fragments; | 359 | u64 tx_bytes[IEEE80211_NUM_ACS]; |
359 | struct ieee80211_tx_rate last_tx_rate; | 360 | struct ieee80211_tx_rate last_tx_rate; |
360 | int last_rx_rate_idx; | 361 | int last_rx_rate_idx; |
361 | u32 last_rx_rate_flag; | 362 | u32 last_rx_rate_flag; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e7db2b804e0c..c5899797a8d4 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -431,6 +431,30 @@ TRACE_EVENT(drv_prepare_multicast, | |||
431 | ) | 431 | ) |
432 | ); | 432 | ); |
433 | 433 | ||
434 | TRACE_EVENT(drv_set_multicast_list, | ||
435 | TP_PROTO(struct ieee80211_local *local, | ||
436 | struct ieee80211_sub_if_data *sdata, int mc_count), | ||
437 | |||
438 | TP_ARGS(local, sdata, mc_count), | ||
439 | |||
440 | TP_STRUCT__entry( | ||
441 | LOCAL_ENTRY | ||
442 | __field(bool, allmulti) | ||
443 | __field(int, mc_count) | ||
444 | ), | ||
445 | |||
446 | TP_fast_assign( | ||
447 | LOCAL_ASSIGN; | ||
448 | __entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
449 | __entry->mc_count = mc_count; | ||
450 | ), | ||
451 | |||
452 | TP_printk( | ||
453 | LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d", | ||
454 | LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti | ||
455 | ) | ||
456 | ); | ||
457 | |||
434 | TRACE_EVENT(drv_configure_filter, | 458 | TRACE_EVENT(drv_configure_filter, |
435 | TP_PROTO(struct ieee80211_local *local, | 459 | TP_PROTO(struct ieee80211_local *local, |
436 | unsigned int changed_flags, | 460 | unsigned int changed_flags, |
@@ -940,23 +964,26 @@ TRACE_EVENT(drv_get_survey, | |||
940 | ); | 964 | ); |
941 | 965 | ||
942 | TRACE_EVENT(drv_flush, | 966 | TRACE_EVENT(drv_flush, |
943 | TP_PROTO(struct ieee80211_local *local, bool drop), | 967 | TP_PROTO(struct ieee80211_local *local, |
968 | u32 queues, bool drop), | ||
944 | 969 | ||
945 | TP_ARGS(local, drop), | 970 | TP_ARGS(local, queues, drop), |
946 | 971 | ||
947 | TP_STRUCT__entry( | 972 | TP_STRUCT__entry( |
948 | LOCAL_ENTRY | 973 | LOCAL_ENTRY |
949 | __field(bool, drop) | 974 | __field(bool, drop) |
975 | __field(u32, queues) | ||
950 | ), | 976 | ), |
951 | 977 | ||
952 | TP_fast_assign( | 978 | TP_fast_assign( |
953 | LOCAL_ASSIGN; | 979 | LOCAL_ASSIGN; |
954 | __entry->drop = drop; | 980 | __entry->drop = drop; |
981 | __entry->queues = queues; | ||
955 | ), | 982 | ), |
956 | 983 | ||
957 | TP_printk( | 984 | TP_printk( |
958 | LOCAL_PR_FMT " drop:%d", | 985 | LOCAL_PR_FMT " queues:0x%x drop:%d", |
959 | LOCAL_PR_ARG, __entry->drop | 986 | LOCAL_PR_ARG, __entry->queues, __entry->drop |
960 | ) | 987 | ) |
961 | ); | 988 | ); |
962 | 989 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4e8a86163fc7..9e67cc97b87b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -233,6 +233,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
233 | 233 | ||
234 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 234 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
235 | ieee80211_stop_queues_by_reason(&local->hw, | 235 | ieee80211_stop_queues_by_reason(&local->hw, |
236 | IEEE80211_MAX_QUEUE_MAP, | ||
236 | IEEE80211_QUEUE_STOP_REASON_PS); | 237 | IEEE80211_QUEUE_STOP_REASON_PS); |
237 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 238 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
238 | ieee80211_queue_work(&local->hw, | 239 | ieee80211_queue_work(&local->hw, |
@@ -991,15 +992,18 @@ static ieee80211_tx_result debug_noinline | |||
991 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 992 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
992 | { | 993 | { |
993 | struct sk_buff *skb; | 994 | struct sk_buff *skb; |
995 | int ac = -1; | ||
994 | 996 | ||
995 | if (!tx->sta) | 997 | if (!tx->sta) |
996 | return TX_CONTINUE; | 998 | return TX_CONTINUE; |
997 | 999 | ||
998 | tx->sta->tx_packets++; | ||
999 | skb_queue_walk(&tx->skbs, skb) { | 1000 | skb_queue_walk(&tx->skbs, skb) { |
1001 | ac = skb_get_queue_mapping(skb); | ||
1000 | tx->sta->tx_fragments++; | 1002 | tx->sta->tx_fragments++; |
1001 | tx->sta->tx_bytes += skb->len; | 1003 | tx->sta->tx_bytes[ac] += skb->len; |
1002 | } | 1004 | } |
1005 | if (ac >= 0) | ||
1006 | tx->sta->tx_packets[ac]++; | ||
1003 | 1007 | ||
1004 | return TX_CONTINUE; | 1008 | return TX_CONTINUE; |
1005 | } | 1009 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b7a856e3281b..a7368870c8ee 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -453,7 +453,8 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
453 | } | 453 | } |
454 | 454 | ||
455 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 455 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
456 | enum queue_stop_reason reason) | 456 | unsigned long queues, |
457 | enum queue_stop_reason reason) | ||
457 | { | 458 | { |
458 | struct ieee80211_local *local = hw_to_local(hw); | 459 | struct ieee80211_local *local = hw_to_local(hw); |
459 | unsigned long flags; | 460 | unsigned long flags; |
@@ -461,7 +462,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | |||
461 | 462 | ||
462 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 463 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
463 | 464 | ||
464 | for (i = 0; i < hw->queues; i++) | 465 | for_each_set_bit(i, &queues, hw->queues) |
465 | __ieee80211_stop_queue(hw, i, reason); | 466 | __ieee80211_stop_queue(hw, i, reason); |
466 | 467 | ||
467 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 468 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
@@ -469,7 +470,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | |||
469 | 470 | ||
470 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 471 | void ieee80211_stop_queues(struct ieee80211_hw *hw) |
471 | { | 472 | { |
472 | ieee80211_stop_queues_by_reason(hw, | 473 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
473 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | 474 | IEEE80211_QUEUE_STOP_REASON_DRIVER); |
474 | } | 475 | } |
475 | EXPORT_SYMBOL(ieee80211_stop_queues); | 476 | EXPORT_SYMBOL(ieee80211_stop_queues); |
@@ -491,6 +492,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | |||
491 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 492 | EXPORT_SYMBOL(ieee80211_queue_stopped); |
492 | 493 | ||
493 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 494 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
495 | unsigned long queues, | ||
494 | enum queue_stop_reason reason) | 496 | enum queue_stop_reason reason) |
495 | { | 497 | { |
496 | struct ieee80211_local *local = hw_to_local(hw); | 498 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -499,7 +501,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | |||
499 | 501 | ||
500 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 502 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
501 | 503 | ||
502 | for (i = 0; i < hw->queues; i++) | 504 | for_each_set_bit(i, &queues, hw->queues) |
503 | __ieee80211_wake_queue(hw, i, reason); | 505 | __ieee80211_wake_queue(hw, i, reason); |
504 | 506 | ||
505 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 507 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
@@ -507,10 +509,42 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | |||
507 | 509 | ||
508 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 510 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
509 | { | 511 | { |
510 | ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER); | 512 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
513 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | ||
511 | } | 514 | } |
512 | EXPORT_SYMBOL(ieee80211_wake_queues); | 515 | EXPORT_SYMBOL(ieee80211_wake_queues); |
513 | 516 | ||
517 | void ieee80211_flush_queues(struct ieee80211_local *local, | ||
518 | struct ieee80211_sub_if_data *sdata) | ||
519 | { | ||
520 | u32 queues; | ||
521 | |||
522 | if (!local->ops->flush) | ||
523 | return; | ||
524 | |||
525 | if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) { | ||
526 | int ac; | ||
527 | |||
528 | queues = 0; | ||
529 | |||
530 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
531 | queues |= BIT(sdata->vif.hw_queue[ac]); | ||
532 | if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE) | ||
533 | queues |= BIT(sdata->vif.cab_queue); | ||
534 | } else { | ||
535 | /* all queues */ | ||
536 | queues = BIT(local->hw.queues) - 1; | ||
537 | } | ||
538 | |||
539 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | ||
540 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | ||
541 | |||
542 | drv_flush(local, queues, false); | ||
543 | |||
544 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | ||
545 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | ||
546 | } | ||
547 | |||
514 | void ieee80211_iterate_active_interfaces( | 548 | void ieee80211_iterate_active_interfaces( |
515 | struct ieee80211_hw *hw, u32 iter_flags, | 549 | struct ieee80211_hw *hw, u32 iter_flags, |
516 | void (*iterator)(void *data, u8 *mac, | 550 | void (*iterator)(void *data, u8 *mac, |
@@ -1651,8 +1685,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1651 | mutex_unlock(&local->sta_mtx); | 1685 | mutex_unlock(&local->sta_mtx); |
1652 | } | 1686 | } |
1653 | 1687 | ||
1654 | ieee80211_wake_queues_by_reason(hw, | 1688 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
1655 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1689 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
1656 | 1690 | ||
1657 | /* | 1691 | /* |
1658 | * If this is for hw restart things are still running. | 1692 | * If this is for hw restart things are still running. |