diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 150 |
1 files changed, 99 insertions, 51 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 9ed49ad0380f..60f1ce5e5e52 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Interface handling (except master interface) | 2 | * Interface handling |
3 | * | 3 | * |
4 | * Copyright 2002-2005, Instant802 Networks, Inc. | 4 | * Copyright 2002-2005, Instant802 Networks, Inc. |
5 | * Copyright 2005-2006, Devicescape Software, Inc. | 5 | * Copyright 2005-2006, Devicescape Software, Inc. |
@@ -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; |
@@ -357,7 +357,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
357 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 357 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
358 | } | 358 | } |
359 | 359 | ||
360 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 360 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
361 | { | 361 | { |
362 | struct ieee80211_sub_if_data *sdata; | 362 | struct ieee80211_sub_if_data *sdata; |
363 | int ret; | 363 | int ret; |
@@ -410,7 +410,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
410 | return 0; | 410 | return 0; |
411 | } | 411 | } |
412 | 412 | ||
413 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 413 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
414 | { | 414 | { |
415 | struct ieee80211_sub_if_data *sdata; | 415 | struct ieee80211_sub_if_data *sdata; |
416 | 416 | ||
@@ -499,8 +499,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
499 | res = drv_start(local); | 499 | res = drv_start(local); |
500 | if (res) | 500 | if (res) |
501 | goto err_del_bss; | 501 | goto err_del_bss; |
502 | if (local->ops->napi_poll) | ||
503 | napi_enable(&local->napi); | ||
504 | /* we're brought up, everything changes */ | 502 | /* we're brought up, everything changes */ |
505 | hw_reconf_flags = ~0; | 503 | hw_reconf_flags = ~0; |
506 | ieee80211_led_radio(local, true); | 504 | ieee80211_led_radio(local, true); |
@@ -573,8 +571,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
573 | goto err_del_interface; | 571 | goto err_del_interface; |
574 | } | 572 | } |
575 | 573 | ||
576 | drv_add_interface_debugfs(local, sdata); | ||
577 | |||
578 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 574 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
579 | local->fif_pspoll++; | 575 | local->fif_pspoll++; |
580 | local->fif_probe_req++; | 576 | local->fif_probe_req++; |
@@ -599,7 +595,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
599 | case NL80211_IFTYPE_P2P_DEVICE: | 595 | case NL80211_IFTYPE_P2P_DEVICE: |
600 | break; | 596 | break; |
601 | default: | 597 | default: |
602 | netif_carrier_on(dev); | 598 | /* not reached */ |
599 | WARN_ON(1); | ||
603 | } | 600 | } |
604 | 601 | ||
605 | /* | 602 | /* |
@@ -656,8 +653,28 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
656 | 653 | ||
657 | ieee80211_recalc_ps(local, -1); | 654 | ieee80211_recalc_ps(local, -1); |
658 | 655 | ||
659 | if (dev) | 656 | if (dev) { |
660 | netif_tx_start_all_queues(dev); | 657 | unsigned long flags; |
658 | int n_acs = IEEE80211_NUM_ACS; | ||
659 | int ac; | ||
660 | |||
661 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
662 | n_acs = 1; | ||
663 | |||
664 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
665 | if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE || | ||
666 | (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 && | ||
667 | skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) { | ||
668 | for (ac = 0; ac < n_acs; ac++) { | ||
669 | int ac_queue = sdata->vif.hw_queue[ac]; | ||
670 | |||
671 | if (local->queue_stop_reasons[ac_queue] == 0 && | ||
672 | skb_queue_empty(&local->pending[ac_queue])) | ||
673 | netif_start_subqueue(dev, ac); | ||
674 | } | ||
675 | } | ||
676 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
677 | } | ||
661 | 678 | ||
662 | return 0; | 679 | return 0; |
663 | err_del_interface: | 680 | err_del_interface: |
@@ -711,7 +728,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
711 | if (sdata->dev) | 728 | if (sdata->dev) |
712 | netif_tx_stop_all_queues(sdata->dev); | 729 | netif_tx_stop_all_queues(sdata->dev); |
713 | 730 | ||
714 | ieee80211_roc_purge(sdata); | 731 | ieee80211_roc_purge(local, sdata); |
715 | 732 | ||
716 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 733 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
717 | ieee80211_mgd_stop(sdata); | 734 | ieee80211_mgd_stop(sdata); |
@@ -736,12 +753,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
736 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 753 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
737 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 754 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
738 | 755 | ||
739 | /* | 756 | /* don't count this interface for promisc/allmulti while it is down */ |
740 | * Don't count this interface for promisc/allmulti while it | ||
741 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
742 | * on the master interface which will sync these down to the | ||
743 | * hardware as filter flags. | ||
744 | */ | ||
745 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 757 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
746 | atomic_dec(&local->iff_allmultis); | 758 | atomic_dec(&local->iff_allmultis); |
747 | 759 | ||
@@ -762,8 +774,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
762 | sdata->dev->addr_len); | 774 | sdata->dev->addr_len); |
763 | spin_unlock_bh(&local->filter_lock); | 775 | spin_unlock_bh(&local->filter_lock); |
764 | netif_addr_unlock_bh(sdata->dev); | 776 | netif_addr_unlock_bh(sdata->dev); |
765 | |||
766 | ieee80211_configure_filter(local); | ||
767 | } | 777 | } |
768 | 778 | ||
769 | del_timer_sync(&local->dynamic_ps_timer); | 779 | del_timer_sync(&local->dynamic_ps_timer); |
@@ -774,6 +784,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
774 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 784 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
775 | 785 | ||
776 | if (sdata->wdev.cac_started) { | 786 | if (sdata->wdev.cac_started) { |
787 | WARN_ON(local->suspended); | ||
777 | mutex_lock(&local->iflist_mtx); | 788 | mutex_lock(&local->iflist_mtx); |
778 | ieee80211_vif_release_channel(sdata); | 789 | ieee80211_vif_release_channel(sdata); |
779 | mutex_unlock(&local->iflist_mtx); | 790 | mutex_unlock(&local->iflist_mtx); |
@@ -824,14 +835,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
824 | if (local->monitors == 0) { | 835 | if (local->monitors == 0) { |
825 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; | 836 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; |
826 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 837 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
827 | ieee80211_del_virtual_monitor(local); | ||
828 | } | 838 | } |
829 | 839 | ||
830 | ieee80211_adjust_monitor_flags(sdata, -1); | 840 | ieee80211_adjust_monitor_flags(sdata, -1); |
831 | ieee80211_configure_filter(local); | ||
832 | mutex_lock(&local->mtx); | ||
833 | ieee80211_recalc_idle(local); | ||
834 | mutex_unlock(&local->mtx); | ||
835 | break; | 841 | break; |
836 | case NL80211_IFTYPE_P2P_DEVICE: | 842 | case NL80211_IFTYPE_P2P_DEVICE: |
837 | /* relies on synchronize_rcu() below */ | 843 | /* relies on synchronize_rcu() below */ |
@@ -844,46 +850,28 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
844 | * | 850 | * |
845 | * sta_info_flush_cleanup() requires rcu_barrier() | 851 | * sta_info_flush_cleanup() requires rcu_barrier() |
846 | * first to wait for the station call_rcu() calls | 852 | * first to wait for the station call_rcu() calls |
847 | * to complete, here we need at least sychronize_rcu() | 853 | * to complete, and we also need synchronize_rcu() |
848 | * it to wait for the RX path in case it is using the | 854 | * to wait for the RX path in case it is using the |
849 | * interface and enqueuing frames at this very time on | 855 | * interface and enqueuing frames at this very time on |
850 | * another CPU. | 856 | * another CPU. |
851 | */ | 857 | */ |
858 | synchronize_rcu(); | ||
852 | rcu_barrier(); | 859 | rcu_barrier(); |
853 | sta_info_flush_cleanup(sdata); | 860 | sta_info_flush_cleanup(sdata); |
854 | 861 | ||
855 | skb_queue_purge(&sdata->skb_queue); | ||
856 | |||
857 | /* | 862 | /* |
858 | * Free all remaining keys, there shouldn't be any, | 863 | * Free all remaining keys, there shouldn't be any, |
859 | * except maybe group keys in AP more or WDS? | 864 | * except maybe in WDS mode? |
860 | */ | 865 | */ |
861 | ieee80211_free_keys(sdata); | 866 | ieee80211_free_keys(sdata); |
862 | 867 | ||
863 | drv_remove_interface_debugfs(local, sdata); | 868 | /* fall through */ |
864 | 869 | case NL80211_IFTYPE_AP: | |
865 | if (going_down) | 870 | skb_queue_purge(&sdata->skb_queue); |
866 | drv_remove_interface(local, sdata); | ||
867 | } | 871 | } |
868 | 872 | ||
869 | sdata->bss = NULL; | 873 | sdata->bss = NULL; |
870 | 874 | ||
871 | ieee80211_recalc_ps(local, -1); | ||
872 | |||
873 | if (local->open_count == 0) { | ||
874 | if (local->ops->napi_poll) | ||
875 | napi_disable(&local->napi); | ||
876 | ieee80211_clear_tx_pending(local); | ||
877 | ieee80211_stop_device(local); | ||
878 | |||
879 | /* no reconfiguring after stop! */ | ||
880 | hw_reconf_flags = 0; | ||
881 | } | ||
882 | |||
883 | /* do after stop to avoid reconfiguring when we stop anyway */ | ||
884 | if (hw_reconf_flags) | ||
885 | ieee80211_hw_config(local, hw_reconf_flags); | ||
886 | |||
887 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 875 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
888 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 876 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
889 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { | 877 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { |
@@ -896,7 +884,54 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
896 | } | 884 | } |
897 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 885 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
898 | 886 | ||
899 | if (local->monitors == local->open_count && local->monitors > 0) | 887 | if (local->open_count == 0) |
888 | ieee80211_clear_tx_pending(local); | ||
889 | |||
890 | /* | ||
891 | * If the interface goes down while suspended, presumably because | ||
892 | * the device was unplugged and that happens before our resume, | ||
893 | * then the driver is already unconfigured and the remainder of | ||
894 | * this function isn't needed. | ||
895 | * XXX: what about WoWLAN? If the device has software state, e.g. | ||
896 | * memory allocated, it might expect teardown commands from | ||
897 | * mac80211 here? | ||
898 | */ | ||
899 | if (local->suspended) { | ||
900 | WARN_ON(local->wowlan); | ||
901 | WARN_ON(rtnl_dereference(local->monitor_sdata)); | ||
902 | return; | ||
903 | } | ||
904 | |||
905 | switch (sdata->vif.type) { | ||
906 | case NL80211_IFTYPE_AP_VLAN: | ||
907 | break; | ||
908 | case NL80211_IFTYPE_MONITOR: | ||
909 | if (local->monitors == 0) | ||
910 | ieee80211_del_virtual_monitor(local); | ||
911 | |||
912 | mutex_lock(&local->mtx); | ||
913 | ieee80211_recalc_idle(local); | ||
914 | mutex_unlock(&local->mtx); | ||
915 | break; | ||
916 | default: | ||
917 | if (going_down) | ||
918 | drv_remove_interface(local, sdata); | ||
919 | } | ||
920 | |||
921 | ieee80211_recalc_ps(local, -1); | ||
922 | |||
923 | if (local->open_count == 0) { | ||
924 | ieee80211_stop_device(local); | ||
925 | |||
926 | /* no reconfiguring after stop! */ | ||
927 | return; | ||
928 | } | ||
929 | |||
930 | /* do after stop to avoid reconfiguring when we stop anyway */ | ||
931 | ieee80211_configure_filter(local); | ||
932 | ieee80211_hw_config(local, hw_reconf_flags); | ||
933 | |||
934 | if (local->monitors == local->open_count) | ||
900 | ieee80211_add_virtual_monitor(local); | 935 | ieee80211_add_virtual_monitor(local); |
901 | } | 936 | } |
902 | 937 | ||
@@ -935,6 +970,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
935 | atomic_dec(&local->iff_promiscs); | 970 | atomic_dec(&local->iff_promiscs); |
936 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 971 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
937 | } | 972 | } |
973 | |||
974 | /* | ||
975 | * TODO: If somebody needs this on AP interfaces, | ||
976 | * it can be enabled easily but multicast | ||
977 | * addresses from VLANs need to be synced. | ||
978 | */ | ||
979 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
980 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
981 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
982 | drv_set_multicast_list(local, sdata, &dev->mc); | ||
983 | |||
938 | spin_lock_bh(&local->filter_lock); | 984 | spin_lock_bh(&local->filter_lock); |
939 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 985 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
940 | spin_unlock_bh(&local->filter_lock); | 986 | spin_unlock_bh(&local->filter_lock); |
@@ -1561,6 +1607,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1561 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); | 1607 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); |
1562 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, | 1608 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, |
1563 | ieee80211_dfs_cac_timer_work); | 1609 | ieee80211_dfs_cac_timer_work); |
1610 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, | ||
1611 | ieee80211_delayed_tailroom_dec); | ||
1564 | 1612 | ||
1565 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1613 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1566 | struct ieee80211_supported_band *sband; | 1614 | struct ieee80211_supported_band *sband; |