diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 111 |
1 files changed, 49 insertions, 62 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a0757913046e..ce1c44370610 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -401,6 +401,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
401 | snprintf(sdata->name, IFNAMSIZ, "%s-monitor", | 401 | snprintf(sdata->name, IFNAMSIZ, "%s-monitor", |
402 | wiphy_name(local->hw.wiphy)); | 402 | wiphy_name(local->hw.wiphy)); |
403 | 403 | ||
404 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
405 | |||
404 | ieee80211_set_default_queues(sdata); | 406 | ieee80211_set_default_queues(sdata); |
405 | 407 | ||
406 | ret = drv_add_interface(local, sdata); | 408 | ret = drv_add_interface(local, sdata); |
@@ -416,18 +418,24 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
416 | return ret; | 418 | return ret; |
417 | } | 419 | } |
418 | 420 | ||
421 | mutex_lock(&local->iflist_mtx); | ||
422 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
423 | mutex_unlock(&local->iflist_mtx); | ||
424 | |||
425 | mutex_lock(&local->mtx); | ||
419 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 426 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
420 | IEEE80211_CHANCTX_EXCLUSIVE); | 427 | IEEE80211_CHANCTX_EXCLUSIVE); |
428 | mutex_unlock(&local->mtx); | ||
421 | if (ret) { | 429 | if (ret) { |
430 | mutex_lock(&local->iflist_mtx); | ||
431 | rcu_assign_pointer(local->monitor_sdata, NULL); | ||
432 | mutex_unlock(&local->iflist_mtx); | ||
433 | synchronize_net(); | ||
422 | drv_remove_interface(local, sdata); | 434 | drv_remove_interface(local, sdata); |
423 | kfree(sdata); | 435 | kfree(sdata); |
424 | return ret; | 436 | return ret; |
425 | } | 437 | } |
426 | 438 | ||
427 | mutex_lock(&local->iflist_mtx); | ||
428 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
429 | mutex_unlock(&local->iflist_mtx); | ||
430 | |||
431 | return 0; | 439 | return 0; |
432 | } | 440 | } |
433 | 441 | ||
@@ -454,7 +462,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
454 | 462 | ||
455 | synchronize_net(); | 463 | synchronize_net(); |
456 | 464 | ||
465 | mutex_lock(&local->mtx); | ||
457 | ieee80211_vif_release_channel(sdata); | 466 | ieee80211_vif_release_channel(sdata); |
467 | mutex_unlock(&local->mtx); | ||
458 | 468 | ||
459 | drv_remove_interface(local, sdata); | 469 | drv_remove_interface(local, sdata); |
460 | 470 | ||
@@ -749,6 +759,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
749 | u32 hw_reconf_flags = 0; | 759 | u32 hw_reconf_flags = 0; |
750 | int i, flushed; | 760 | int i, flushed; |
751 | struct ps_data *ps; | 761 | struct ps_data *ps; |
762 | struct cfg80211_chan_def chandef; | ||
752 | 763 | ||
753 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 764 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
754 | 765 | ||
@@ -763,12 +774,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
763 | 774 | ||
764 | ieee80211_roc_purge(local, sdata); | 775 | ieee80211_roc_purge(local, sdata); |
765 | 776 | ||
766 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 777 | switch (sdata->vif.type) { |
778 | case NL80211_IFTYPE_STATION: | ||
767 | ieee80211_mgd_stop(sdata); | 779 | ieee80211_mgd_stop(sdata); |
768 | 780 | break; | |
769 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 781 | case NL80211_IFTYPE_ADHOC: |
770 | ieee80211_ibss_stop(sdata); | 782 | ieee80211_ibss_stop(sdata); |
771 | 783 | break; | |
784 | case NL80211_IFTYPE_AP: | ||
785 | cancel_work_sync(&sdata->u.ap.request_smps_work); | ||
786 | break; | ||
787 | default: | ||
788 | break; | ||
789 | } | ||
772 | 790 | ||
773 | /* | 791 | /* |
774 | * Remove all stations associated with this interface. | 792 | * Remove all stations associated with this interface. |
@@ -783,10 +801,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
783 | * This is relevant only in WDS mode, in all other modes we've | 801 | * This is relevant only in WDS mode, in all other modes we've |
784 | * already removed all stations when disconnecting or similar, | 802 | * already removed all stations when disconnecting or similar, |
785 | * so warn otherwise. | 803 | * so warn otherwise. |
786 | * | ||
787 | * We call sta_info_flush_cleanup() later, to combine RCU waits. | ||
788 | */ | 804 | */ |
789 | flushed = sta_info_flush_defer(sdata); | 805 | flushed = sta_info_flush(sdata); |
790 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 806 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
791 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 807 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
792 | 808 | ||
@@ -823,11 +839,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
823 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 839 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
824 | 840 | ||
825 | if (sdata->wdev.cac_started) { | 841 | if (sdata->wdev.cac_started) { |
842 | chandef = sdata->vif.bss_conf.chandef; | ||
826 | WARN_ON(local->suspended); | 843 | WARN_ON(local->suspended); |
827 | mutex_lock(&local->iflist_mtx); | 844 | mutex_lock(&local->mtx); |
828 | ieee80211_vif_release_channel(sdata); | 845 | ieee80211_vif_release_channel(sdata); |
829 | mutex_unlock(&local->iflist_mtx); | 846 | mutex_unlock(&local->mtx); |
830 | cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, | 847 | cfg80211_cac_event(sdata->dev, &chandef, |
848 | NL80211_RADAR_CAC_ABORTED, | ||
831 | GFP_KERNEL); | 849 | GFP_KERNEL); |
832 | } | 850 | } |
833 | 851 | ||
@@ -886,23 +904,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
886 | cancel_work_sync(&sdata->work); | 904 | cancel_work_sync(&sdata->work); |
887 | /* | 905 | /* |
888 | * When we get here, the interface is marked down. | 906 | * When we get here, the interface is marked down. |
907 | * Free the remaining keys, if there are any | ||
908 | * (shouldn't be, except maybe in WDS mode?) | ||
889 | * | 909 | * |
890 | * sta_info_flush_cleanup() requires rcu_barrier() | 910 | * Force the key freeing to always synchronize_net() |
891 | * first to wait for the station call_rcu() calls | 911 | * to wait for the RX path in case it is using this |
892 | * to complete, and we also need synchronize_rcu() | 912 | * interface enqueuing frames * at this very time on |
893 | * to wait for the RX path in case it is using the | ||
894 | * interface and enqueuing frames at this very time on | ||
895 | * another CPU. | 913 | * another CPU. |
896 | */ | 914 | */ |
897 | synchronize_rcu(); | 915 | ieee80211_free_keys(sdata, true); |
898 | rcu_barrier(); | ||
899 | sta_info_flush_cleanup(sdata); | ||
900 | |||
901 | /* | ||
902 | * Free all remaining keys, there shouldn't be any, | ||
903 | * except maybe in WDS mode? | ||
904 | */ | ||
905 | ieee80211_free_keys(sdata); | ||
906 | 916 | ||
907 | /* fall through */ | 917 | /* fall through */ |
908 | case NL80211_IFTYPE_AP: | 918 | case NL80211_IFTYPE_AP: |
@@ -1013,17 +1023,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
1013 | atomic_dec(&local->iff_promiscs); | 1023 | atomic_dec(&local->iff_promiscs); |
1014 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 1024 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
1015 | } | 1025 | } |
1016 | |||
1017 | /* | ||
1018 | * TODO: If somebody needs this on AP interfaces, | ||
1019 | * it can be enabled easily but multicast | ||
1020 | * addresses from VLANs need to be synced. | ||
1021 | */ | ||
1022 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
1023 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
1024 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
1025 | drv_set_multicast_list(local, sdata, &dev->mc); | ||
1026 | |||
1027 | spin_lock_bh(&local->filter_lock); | 1026 | spin_lock_bh(&local->filter_lock); |
1028 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 1027 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
1029 | spin_unlock_bh(&local->filter_lock); | 1028 | spin_unlock_bh(&local->filter_lock); |
@@ -1036,11 +1035,10 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
1036 | */ | 1035 | */ |
1037 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | 1036 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) |
1038 | { | 1037 | { |
1039 | int flushed; | ||
1040 | int i; | 1038 | int i; |
1041 | 1039 | ||
1042 | /* free extra data */ | 1040 | /* free extra data */ |
1043 | ieee80211_free_keys(sdata); | 1041 | ieee80211_free_keys(sdata, false); |
1044 | 1042 | ||
1045 | ieee80211_debugfs_remove_netdev(sdata); | 1043 | ieee80211_debugfs_remove_netdev(sdata); |
1046 | 1044 | ||
@@ -1050,9 +1048,6 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | |||
1050 | 1048 | ||
1051 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1049 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1052 | mesh_rmc_free(sdata); | 1050 | mesh_rmc_free(sdata); |
1053 | |||
1054 | flushed = sta_info_flush(sdata); | ||
1055 | WARN_ON(flushed); | ||
1056 | } | 1051 | } |
1057 | 1052 | ||
1058 | static void ieee80211_uninit(struct net_device *dev) | 1053 | static void ieee80211_uninit(struct net_device *dev) |
@@ -1062,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev) | |||
1062 | 1057 | ||
1063 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, | 1058 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, |
1064 | struct sk_buff *skb, | 1059 | struct sk_buff *skb, |
1065 | void *accel_priv) | 1060 | void *accel_priv, |
1061 | select_queue_fallback_t fallback) | ||
1066 | { | 1062 | { |
1067 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); | 1063 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); |
1068 | } | 1064 | } |
@@ -1080,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
1080 | 1076 | ||
1081 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, | 1077 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, |
1082 | struct sk_buff *skb, | 1078 | struct sk_buff *skb, |
1083 | void *accel_priv) | 1079 | void *accel_priv, |
1080 | select_queue_fallback_t fallback) | ||
1084 | { | 1081 | { |
1085 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1082 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1086 | struct ieee80211_local *local = sdata->local; | 1083 | struct ieee80211_local *local = sdata->local; |
@@ -1272,6 +1269,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1272 | 1269 | ||
1273 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | 1270 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); |
1274 | sdata->control_port_no_encrypt = false; | 1271 | sdata->control_port_no_encrypt = false; |
1272 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
1275 | 1273 | ||
1276 | sdata->noack_map = 0; | 1274 | sdata->noack_map = 0; |
1277 | 1275 | ||
@@ -1497,8 +1495,8 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1497 | bool used = false; | 1495 | bool used = false; |
1498 | 1496 | ||
1499 | list_for_each_entry(sdata, &local->interfaces, list) { | 1497 | list_for_each_entry(sdata, &local->interfaces, list) { |
1500 | if (memcmp(local->hw.wiphy->addresses[i].addr, | 1498 | if (ether_addr_equal(local->hw.wiphy->addresses[i].addr, |
1501 | sdata->vif.addr, ETH_ALEN) == 0) { | 1499 | sdata->vif.addr)) { |
1502 | used = true; | 1500 | used = true; |
1503 | break; | 1501 | break; |
1504 | } | 1502 | } |
@@ -1558,8 +1556,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1558 | val += inc; | 1556 | val += inc; |
1559 | 1557 | ||
1560 | list_for_each_entry(sdata, &local->interfaces, list) { | 1558 | list_for_each_entry(sdata, &local->interfaces, list) { |
1561 | if (memcmp(tmp_addr, sdata->vif.addr, | 1559 | if (ether_addr_equal(tmp_addr, sdata->vif.addr)) { |
1562 | ETH_ALEN) == 0) { | ||
1563 | used = true; | 1560 | used = true; |
1564 | break; | 1561 | break; |
1565 | } | 1562 | } |
@@ -1579,15 +1576,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1579 | mutex_unlock(&local->iflist_mtx); | 1576 | mutex_unlock(&local->iflist_mtx); |
1580 | } | 1577 | } |
1581 | 1578 | ||
1582 | static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) | ||
1583 | { | ||
1584 | struct ieee80211_sub_if_data *sdata; | ||
1585 | |||
1586 | sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); | ||
1587 | |||
1588 | ieee80211_cleanup_sdata_stas(sdata); | ||
1589 | } | ||
1590 | |||
1591 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1579 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1592 | struct wireless_dev **new_wdev, enum nl80211_iftype type, | 1580 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1593 | struct vif_params *params) | 1581 | struct vif_params *params) |
@@ -1660,9 +1648,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1660 | 1648 | ||
1661 | INIT_LIST_HEAD(&sdata->key_list); | 1649 | INIT_LIST_HEAD(&sdata->key_list); |
1662 | 1650 | ||
1663 | spin_lock_init(&sdata->cleanup_stations_lock); | ||
1664 | INIT_LIST_HEAD(&sdata->cleanup_stations); | ||
1665 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); | ||
1666 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, | 1651 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, |
1667 | ieee80211_dfs_cac_timer_work); | 1652 | ieee80211_dfs_cac_timer_work); |
1668 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, | 1653 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, |
@@ -1687,6 +1672,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1687 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; | 1672 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1688 | sdata->user_power_level = local->user_power_level; | 1673 | sdata->user_power_level = local->user_power_level; |
1689 | 1674 | ||
1675 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
1676 | |||
1690 | /* setup type-dependent data */ | 1677 | /* setup type-dependent data */ |
1691 | ieee80211_setup_sdata(sdata, type); | 1678 | ieee80211_setup_sdata(sdata, type); |
1692 | 1679 | ||