diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:09:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:09:54 -0400 |
commit | 655d8e2328a6ef6b6b514609a4c1e33508d3a1da (patch) | |
tree | 144b686bf3fd6512a55987da2d911f739646ce02 /net/mac80211/iface.c | |
parent | 6fe5468f452c0c40348ebd4e737758a842286ca8 (diff) | |
parent | ddc4db2e3d5393ede7a9222bb3b7522a603a4678 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts:
drivers/net/wireless/ath/carl9170/debug.c
drivers/net/wireless/ath/carl9170/main.c
net/mac80211/ieee80211_i.h
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 116 |
1 files changed, 78 insertions, 38 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 69aaba79a9f7..146b1320af4e 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. |
@@ -346,7 +346,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
346 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 346 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
347 | } | 347 | } |
348 | 348 | ||
349 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 349 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
350 | { | 350 | { |
351 | struct ieee80211_sub_if_data *sdata; | 351 | struct ieee80211_sub_if_data *sdata; |
352 | int ret; | 352 | int ret; |
@@ -399,7 +399,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 402 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
403 | { | 403 | { |
404 | struct ieee80211_sub_if_data *sdata; | 404 | struct ieee80211_sub_if_data *sdata; |
405 | 405 | ||
@@ -584,7 +584,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
584 | case NL80211_IFTYPE_P2P_DEVICE: | 584 | case NL80211_IFTYPE_P2P_DEVICE: |
585 | break; | 585 | break; |
586 | default: | 586 | default: |
587 | netif_carrier_on(dev); | 587 | /* not reached */ |
588 | WARN_ON(1); | ||
588 | } | 589 | } |
589 | 590 | ||
590 | /* | 591 | /* |
@@ -641,8 +642,28 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
641 | 642 | ||
642 | ieee80211_recalc_ps(local, -1); | 643 | ieee80211_recalc_ps(local, -1); |
643 | 644 | ||
644 | if (dev) | 645 | if (dev) { |
645 | netif_tx_start_all_queues(dev); | 646 | unsigned long flags; |
647 | int n_acs = IEEE80211_NUM_ACS; | ||
648 | int ac; | ||
649 | |||
650 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
651 | n_acs = 1; | ||
652 | |||
653 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
654 | if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE || | ||
655 | (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 && | ||
656 | skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) { | ||
657 | for (ac = 0; ac < n_acs; ac++) { | ||
658 | int ac_queue = sdata->vif.hw_queue[ac]; | ||
659 | |||
660 | if (local->queue_stop_reasons[ac_queue] == 0 && | ||
661 | skb_queue_empty(&local->pending[ac_queue])) | ||
662 | netif_start_subqueue(dev, ac); | ||
663 | } | ||
664 | } | ||
665 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
666 | } | ||
646 | 667 | ||
647 | return 0; | 668 | return 0; |
648 | err_del_interface: | 669 | err_del_interface: |
@@ -696,7 +717,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
696 | if (sdata->dev) | 717 | if (sdata->dev) |
697 | netif_tx_stop_all_queues(sdata->dev); | 718 | netif_tx_stop_all_queues(sdata->dev); |
698 | 719 | ||
699 | ieee80211_roc_purge(sdata); | 720 | ieee80211_roc_purge(local, sdata); |
700 | 721 | ||
701 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 722 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
702 | ieee80211_mgd_stop(sdata); | 723 | ieee80211_mgd_stop(sdata); |
@@ -721,12 +742,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
721 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 742 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
722 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 743 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
723 | 744 | ||
724 | /* | 745 | /* don't count this interface for promisc/allmulti while it is down */ |
725 | * Don't count this interface for promisc/allmulti while it | ||
726 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
727 | * on the master interface which will sync these down to the | ||
728 | * hardware as filter flags. | ||
729 | */ | ||
730 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 746 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
731 | atomic_dec(&local->iff_allmultis); | 747 | atomic_dec(&local->iff_allmultis); |
732 | 748 | ||
@@ -747,8 +763,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
747 | sdata->dev->addr_len); | 763 | sdata->dev->addr_len); |
748 | spin_unlock_bh(&local->filter_lock); | 764 | spin_unlock_bh(&local->filter_lock); |
749 | netif_addr_unlock_bh(sdata->dev); | 765 | netif_addr_unlock_bh(sdata->dev); |
750 | |||
751 | ieee80211_configure_filter(local); | ||
752 | } | 766 | } |
753 | 767 | ||
754 | del_timer_sync(&local->dynamic_ps_timer); | 768 | del_timer_sync(&local->dynamic_ps_timer); |
@@ -759,6 +773,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
759 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 773 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
760 | 774 | ||
761 | if (sdata->wdev.cac_started) { | 775 | if (sdata->wdev.cac_started) { |
776 | WARN_ON(local->suspended); | ||
762 | mutex_lock(&local->iflist_mtx); | 777 | mutex_lock(&local->iflist_mtx); |
763 | ieee80211_vif_release_channel(sdata); | 778 | ieee80211_vif_release_channel(sdata); |
764 | mutex_unlock(&local->iflist_mtx); | 779 | mutex_unlock(&local->iflist_mtx); |
@@ -809,14 +824,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
809 | if (local->monitors == 0) { | 824 | if (local->monitors == 0) { |
810 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; | 825 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; |
811 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 826 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
812 | ieee80211_del_virtual_monitor(local); | ||
813 | } | 827 | } |
814 | 828 | ||
815 | ieee80211_adjust_monitor_flags(sdata, -1); | 829 | ieee80211_adjust_monitor_flags(sdata, -1); |
816 | ieee80211_configure_filter(local); | ||
817 | mutex_lock(&local->mtx); | ||
818 | ieee80211_recalc_idle(local); | ||
819 | mutex_unlock(&local->mtx); | ||
820 | break; | 830 | break; |
821 | case NL80211_IFTYPE_P2P_DEVICE: | 831 | case NL80211_IFTYPE_P2P_DEVICE: |
822 | /* relies on synchronize_rcu() below */ | 832 | /* relies on synchronize_rcu() below */ |
@@ -846,27 +856,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
846 | /* fall through */ | 856 | /* fall through */ |
847 | case NL80211_IFTYPE_AP: | 857 | case NL80211_IFTYPE_AP: |
848 | skb_queue_purge(&sdata->skb_queue); | 858 | skb_queue_purge(&sdata->skb_queue); |
849 | |||
850 | if (going_down) | ||
851 | drv_remove_interface(local, sdata); | ||
852 | } | 859 | } |
853 | 860 | ||
854 | sdata->bss = NULL; | 861 | sdata->bss = NULL; |
855 | 862 | ||
856 | ieee80211_recalc_ps(local, -1); | ||
857 | |||
858 | if (local->open_count == 0) { | ||
859 | ieee80211_clear_tx_pending(local); | ||
860 | ieee80211_stop_device(local); | ||
861 | |||
862 | /* no reconfiguring after stop! */ | ||
863 | hw_reconf_flags = 0; | ||
864 | } | ||
865 | |||
866 | /* do after stop to avoid reconfiguring when we stop anyway */ | ||
867 | if (hw_reconf_flags) | ||
868 | ieee80211_hw_config(local, hw_reconf_flags); | ||
869 | |||
870 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 863 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
871 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 864 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
872 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { | 865 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { |
@@ -879,7 +872,54 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
879 | } | 872 | } |
880 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 873 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
881 | 874 | ||
882 | if (local->monitors == local->open_count && local->monitors > 0) | 875 | if (local->open_count == 0) |
876 | ieee80211_clear_tx_pending(local); | ||
877 | |||
878 | /* | ||
879 | * If the interface goes down while suspended, presumably because | ||
880 | * the device was unplugged and that happens before our resume, | ||
881 | * then the driver is already unconfigured and the remainder of | ||
882 | * this function isn't needed. | ||
883 | * XXX: what about WoWLAN? If the device has software state, e.g. | ||
884 | * memory allocated, it might expect teardown commands from | ||
885 | * mac80211 here? | ||
886 | */ | ||
887 | if (local->suspended) { | ||
888 | WARN_ON(local->wowlan); | ||
889 | WARN_ON(rtnl_dereference(local->monitor_sdata)); | ||
890 | return; | ||
891 | } | ||
892 | |||
893 | switch (sdata->vif.type) { | ||
894 | case NL80211_IFTYPE_AP_VLAN: | ||
895 | break; | ||
896 | case NL80211_IFTYPE_MONITOR: | ||
897 | if (local->monitors == 0) | ||
898 | ieee80211_del_virtual_monitor(local); | ||
899 | |||
900 | mutex_lock(&local->mtx); | ||
901 | ieee80211_recalc_idle(local); | ||
902 | mutex_unlock(&local->mtx); | ||
903 | break; | ||
904 | default: | ||
905 | if (going_down) | ||
906 | drv_remove_interface(local, sdata); | ||
907 | } | ||
908 | |||
909 | ieee80211_recalc_ps(local, -1); | ||
910 | |||
911 | if (local->open_count == 0) { | ||
912 | ieee80211_stop_device(local); | ||
913 | |||
914 | /* no reconfiguring after stop! */ | ||
915 | return; | ||
916 | } | ||
917 | |||
918 | /* do after stop to avoid reconfiguring when we stop anyway */ | ||
919 | ieee80211_configure_filter(local); | ||
920 | ieee80211_hw_config(local, hw_reconf_flags); | ||
921 | |||
922 | if (local->monitors == local->open_count) | ||
883 | ieee80211_add_virtual_monitor(local); | 923 | ieee80211_add_virtual_monitor(local); |
884 | } | 924 | } |
885 | 925 | ||