diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 256fa19e14ec..8b6daf0219f4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -301,6 +301,8 @@ static int ieee80211_open(struct net_device *dev) | |||
301 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 301 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
302 | atomic_inc(&local->iff_promiscs); | 302 | atomic_inc(&local->iff_promiscs); |
303 | 303 | ||
304 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
305 | |||
304 | local->open_count++; | 306 | local->open_count++; |
305 | if (hw_reconf_flags) { | 307 | if (hw_reconf_flags) { |
306 | ieee80211_hw_config(local, hw_reconf_flags); | 308 | ieee80211_hw_config(local, hw_reconf_flags); |
@@ -548,6 +550,10 @@ static int ieee80211_stop(struct net_device *dev) | |||
548 | 550 | ||
549 | sdata->bss = NULL; | 551 | sdata->bss = NULL; |
550 | 552 | ||
553 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
554 | |||
555 | ieee80211_recalc_ps(local, -1); | ||
556 | |||
551 | if (local->open_count == 0) { | 557 | if (local->open_count == 0) { |
552 | if (netif_running(local->mdev)) | 558 | if (netif_running(local->mdev)) |
553 | dev_close(local->mdev); | 559 | dev_close(local->mdev); |
@@ -565,8 +571,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
565 | hw_reconf_flags = 0; | 571 | hw_reconf_flags = 0; |
566 | } | 572 | } |
567 | 573 | ||
568 | ieee80211_recalc_ps(local, -1); | ||
569 | |||
570 | /* do after stop to avoid reconfiguring when we stop anyway */ | 574 | /* do after stop to avoid reconfiguring when we stop anyway */ |
571 | if (hw_reconf_flags) | 575 | if (hw_reconf_flags) |
572 | ieee80211_hw_config(local, hw_reconf_flags); | 576 | ieee80211_hw_config(local, hw_reconf_flags); |
@@ -892,3 +896,73 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
892 | unregister_netdevice(sdata->dev); | 896 | unregister_netdevice(sdata->dev); |
893 | } | 897 | } |
894 | } | 898 | } |
899 | |||
900 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | ||
901 | const char *reason) | ||
902 | { | ||
903 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | ||
904 | return 0; | ||
905 | |||
906 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
907 | printk(KERN_DEBUG "%s: device no longer idle - %s\n", | ||
908 | wiphy_name(local->hw.wiphy), reason); | ||
909 | #endif | ||
910 | |||
911 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | ||
912 | return IEEE80211_CONF_CHANGE_IDLE; | ||
913 | } | ||
914 | |||
915 | static u32 ieee80211_idle_on(struct ieee80211_local *local) | ||
916 | { | ||
917 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | ||
918 | return 0; | ||
919 | |||
920 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
921 | printk(KERN_DEBUG "%s: device now idle\n", | ||
922 | wiphy_name(local->hw.wiphy)); | ||
923 | #endif | ||
924 | |||
925 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | ||
926 | return IEEE80211_CONF_CHANGE_IDLE; | ||
927 | } | ||
928 | |||
929 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | ||
930 | { | ||
931 | struct ieee80211_sub_if_data *sdata; | ||
932 | int count = 0; | ||
933 | |||
934 | if (local->hw_scanning || local->sw_scanning) | ||
935 | return ieee80211_idle_off(local, "scanning"); | ||
936 | |||
937 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
938 | if (!netif_running(sdata->dev)) | ||
939 | continue; | ||
940 | /* do not count disabled managed interfaces */ | ||
941 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
942 | sdata->u.mgd.state == IEEE80211_STA_MLME_DISABLED) | ||
943 | continue; | ||
944 | /* do not count unused IBSS interfaces */ | ||
945 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
946 | !sdata->u.ibss.ssid_len) | ||
947 | continue; | ||
948 | /* count everything else */ | ||
949 | count++; | ||
950 | } | ||
951 | |||
952 | if (!count) | ||
953 | return ieee80211_idle_on(local); | ||
954 | else | ||
955 | return ieee80211_idle_off(local, "in use"); | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
961 | { | ||
962 | u32 chg; | ||
963 | |||
964 | mutex_lock(&local->iflist_mtx); | ||
965 | chg = __ieee80211_recalc_idle(local); | ||
966 | mutex_unlock(&local->iflist_mtx); | ||
967 | ieee80211_hw_config(local, chg); | ||
968 | } | ||