aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-03-27 18:24:53 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-08 03:17:01 -0400
commitb2c0958b203784659e230bde6bd553d7c37bb4d2 (patch)
tree22fad9aeaac415c114b4a9dfaf765f147d8852b9 /net/mac80211/iface.c
parent3c3e21e7443bdb948437a6e925fd111e932dc083 (diff)
mac80211: fix do_stop handling while suspended
When a device is unplugged while suspended, mac80211 is de-initialized and all interfaces are removed while no state is actually present in the driver. This can cause warnings and driver confusion. Fix this by reordering the do_stop code to not call the driver when it is suspended, i.e. when there's no state in the driver anyway. The previous patches removed a few corner cases in ROC and virtual monitor interfaces so that now this is safe to do and no state should be left over. Reported-by: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c74
1 files changed, 49 insertions, 25 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index d0d5f20f1ec4..8c9419595bc8 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -739,8 +739,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
739 sdata->dev->addr_len); 739 sdata->dev->addr_len);
740 spin_unlock_bh(&local->filter_lock); 740 spin_unlock_bh(&local->filter_lock);
741 netif_addr_unlock_bh(sdata->dev); 741 netif_addr_unlock_bh(sdata->dev);
742
743 ieee80211_configure_filter(local);
744 } 742 }
745 743
746 del_timer_sync(&local->dynamic_ps_timer); 744 del_timer_sync(&local->dynamic_ps_timer);
@@ -751,6 +749,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
751 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); 749 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
752 750
753 if (sdata->wdev.cac_started) { 751 if (sdata->wdev.cac_started) {
752 WARN_ON(local->suspended);
754 mutex_lock(&local->iflist_mtx); 753 mutex_lock(&local->iflist_mtx);
755 ieee80211_vif_release_channel(sdata); 754 ieee80211_vif_release_channel(sdata);
756 mutex_unlock(&local->iflist_mtx); 755 mutex_unlock(&local->iflist_mtx);
@@ -801,14 +800,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
801 if (local->monitors == 0) { 800 if (local->monitors == 0) {
802 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; 801 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
803 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; 802 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
804 ieee80211_del_virtual_monitor(local);
805 } 803 }
806 804
807 ieee80211_adjust_monitor_flags(sdata, -1); 805 ieee80211_adjust_monitor_flags(sdata, -1);
808 ieee80211_configure_filter(local);
809 mutex_lock(&local->mtx);
810 ieee80211_recalc_idle(local);
811 mutex_unlock(&local->mtx);
812 break; 806 break;
813 case NL80211_IFTYPE_P2P_DEVICE: 807 case NL80211_IFTYPE_P2P_DEVICE:
814 /* relies on synchronize_rcu() below */ 808 /* relies on synchronize_rcu() below */
@@ -838,27 +832,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
838 /* fall through */ 832 /* fall through */
839 case NL80211_IFTYPE_AP: 833 case NL80211_IFTYPE_AP:
840 skb_queue_purge(&sdata->skb_queue); 834 skb_queue_purge(&sdata->skb_queue);
841
842 if (going_down)
843 drv_remove_interface(local, sdata);
844 } 835 }
845 836
846 sdata->bss = NULL; 837 sdata->bss = NULL;
847 838
848 ieee80211_recalc_ps(local, -1);
849
850 if (local->open_count == 0) {
851 ieee80211_clear_tx_pending(local);
852 ieee80211_stop_device(local);
853
854 /* no reconfiguring after stop! */
855 hw_reconf_flags = 0;
856 }
857
858 /* do after stop to avoid reconfiguring when we stop anyway */
859 if (hw_reconf_flags)
860 ieee80211_hw_config(local, hw_reconf_flags);
861
862 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 839 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
863 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { 840 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
864 skb_queue_walk_safe(&local->pending[i], skb, tmp) { 841 skb_queue_walk_safe(&local->pending[i], skb, tmp) {
@@ -871,7 +848,54 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
871 } 848 }
872 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 849 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
873 850
874 if (local->monitors == local->open_count && local->monitors > 0) 851 if (local->open_count == 0)
852 ieee80211_clear_tx_pending(local);
853
854 /*
855 * If the interface goes down while suspended, presumably because
856 * the device was unplugged and that happens before our resume,
857 * then the driver is already unconfigured and the remainder of
858 * this function isn't needed.
859 * XXX: what about WoWLAN? If the device has software state, e.g.
860 * memory allocated, it might expect teardown commands from
861 * mac80211 here?
862 */
863 if (local->suspended) {
864 WARN_ON(local->wowlan);
865 WARN_ON(rtnl_dereference(local->monitor_sdata));
866 return;
867 }
868
869 switch (sdata->vif.type) {
870 case NL80211_IFTYPE_AP_VLAN:
871 break;
872 case NL80211_IFTYPE_MONITOR:
873 if (local->monitors == 0)
874 ieee80211_del_virtual_monitor(local);
875
876 mutex_lock(&local->mtx);
877 ieee80211_recalc_idle(local);
878 mutex_unlock(&local->mtx);
879 break;
880 default:
881 if (going_down)
882 drv_remove_interface(local, sdata);
883 }
884
885 ieee80211_recalc_ps(local, -1);
886
887 if (local->open_count == 0) {
888 ieee80211_stop_device(local);
889
890 /* no reconfiguring after stop! */
891 return;
892 }
893
894 /* do after stop to avoid reconfiguring when we stop anyway */
895 ieee80211_configure_filter(local);
896 ieee80211_hw_config(local, hw_reconf_flags);
897
898 if (local->monitors == local->open_count)
875 ieee80211_add_virtual_monitor(local); 899 ieee80211_add_virtual_monitor(local);
876} 900}
877 901