aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-04-29 06:26:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:51 -0400
commit5cff20e6c5a6591a79d3b027af222870f52bb550 (patch)
tree81b6ebb75c1dc87b65258e71526c1581d168156c /net/mac80211/iface.c
parent9955151df7c6452cae2ed9649f53d265c91cf155 (diff)
mac80211: tell driver when idle
When we aren't doing anything in mac80211, we can turn off much of the hardware, depending on the driver/hw. Not doing anything, aka being idle, means: * no monitor interfaces * no AP/mesh/wds interfaces * any station interfaces are in DISABLED state * any IBSS interfaces aren't trying to be in a network * we aren't trying to scan By creating a new function that verifies these conditions and calling it at strategic points where the states of those conditions change, we can easily make mac80211 tell the driver when we are idle to save power. Additionally, this fixes a small quirk where a recalculated powersave state is passed to the driver even if the hardware is about to stopped completely. This patch intentionally doesn't touch radio_enabled because that is currently implemented to be a soft rfkill which is inappropriate here when we need to be able to wake up with low latency. One thing I'm not entirely sure about is this: phy0: device no longer idle - in use wlan0: direct probe to AP 00:11:24:91:07:4d try 1 wlan0 direct probe responded wlan0: authenticate with AP 00:11:24:91:07:4d wlan0: authenticated > phy0: device now idle > phy0: device no longer idle - in use wlan0: associate with AP 00:11:24:91:07:4d wlan0: RX AssocResp from 00:11:24:91:07:4d (capab=0x401 status=0 aid=1) wlan0: associated Is it appropriate to go into idle state for a short time when we have just authenticated, but not associated yet? This happens only with the userspace SME, because we cannot really know how long it will wait before asking us to associate. Would going idle after a short timeout be more appropriate? We may need to revisit this, depending on what happens. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c78
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
900static 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
915static 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
929u32 __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
960void 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}