aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c100
1 files changed, 86 insertions, 14 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 52425975bbbe..8b6daf0219f4 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -20,6 +20,7 @@
20#include "debugfs_netdev.h" 20#include "debugfs_netdev.h"
21#include "mesh.h" 21#include "mesh.h"
22#include "led.h" 22#include "led.h"
23#include "driver-ops.h"
23 24
24/** 25/**
25 * DOC: Interface list locking 26 * DOC: Interface list locking
@@ -164,9 +165,7 @@ static int ieee80211_open(struct net_device *dev)
164 } 165 }
165 166
166 if (local->open_count == 0) { 167 if (local->open_count == 0) {
167 res = 0; 168 res = drv_start(local);
168 if (local->ops->start)
169 res = local->ops->start(local_to_hw(local));
170 if (res) 169 if (res)
171 goto err_del_bss; 170 goto err_del_bss;
172 /* we're brought up, everything changes */ 171 /* we're brought up, everything changes */
@@ -199,8 +198,8 @@ static int ieee80211_open(struct net_device *dev)
199 * Validate the MAC address for this device. 198 * Validate the MAC address for this device.
200 */ 199 */
201 if (!is_valid_ether_addr(dev->dev_addr)) { 200 if (!is_valid_ether_addr(dev->dev_addr)) {
202 if (!local->open_count && local->ops->stop) 201 if (!local->open_count)
203 local->ops->stop(local_to_hw(local)); 202 drv_stop(local);
204 return -EADDRNOTAVAIL; 203 return -EADDRNOTAVAIL;
205 } 204 }
206 205
@@ -241,7 +240,7 @@ static int ieee80211_open(struct net_device *dev)
241 conf.vif = &sdata->vif; 240 conf.vif = &sdata->vif;
242 conf.type = sdata->vif.type; 241 conf.type = sdata->vif.type;
243 conf.mac_addr = dev->dev_addr; 242 conf.mac_addr = dev->dev_addr;
244 res = local->ops->add_interface(local_to_hw(local), &conf); 243 res = drv_add_interface(local, &conf);
245 if (res) 244 if (res)
246 goto err_stop; 245 goto err_stop;
247 246
@@ -302,6 +301,8 @@ static int ieee80211_open(struct net_device *dev)
302 if (sdata->flags & IEEE80211_SDATA_PROMISC) 301 if (sdata->flags & IEEE80211_SDATA_PROMISC)
303 atomic_inc(&local->iff_promiscs); 302 atomic_inc(&local->iff_promiscs);
304 303
304 hw_reconf_flags |= __ieee80211_recalc_idle(local);
305
305 local->open_count++; 306 local->open_count++;
306 if (hw_reconf_flags) { 307 if (hw_reconf_flags) {
307 ieee80211_hw_config(local, hw_reconf_flags); 308 ieee80211_hw_config(local, hw_reconf_flags);
@@ -328,10 +329,10 @@ static int ieee80211_open(struct net_device *dev)
328 329
329 return 0; 330 return 0;
330 err_del_interface: 331 err_del_interface:
331 local->ops->remove_interface(local_to_hw(local), &conf); 332 drv_remove_interface(local, &conf);
332 err_stop: 333 err_stop:
333 if (!local->open_count && local->ops->stop) 334 if (!local->open_count)
334 local->ops->stop(local_to_hw(local)); 335 drv_stop(local);
335 err_del_bss: 336 err_del_bss:
336 sdata->bss = NULL; 337 sdata->bss = NULL;
337 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 338 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -544,17 +545,20 @@ static int ieee80211_stop(struct net_device *dev)
544 conf.mac_addr = dev->dev_addr; 545 conf.mac_addr = dev->dev_addr;
545 /* disable all keys for as long as this netdev is down */ 546 /* disable all keys for as long as this netdev is down */
546 ieee80211_disable_keys(sdata); 547 ieee80211_disable_keys(sdata);
547 local->ops->remove_interface(local_to_hw(local), &conf); 548 drv_remove_interface(local, &conf);
548 } 549 }
549 550
550 sdata->bss = NULL; 551 sdata->bss = NULL;
551 552
553 hw_reconf_flags |= __ieee80211_recalc_idle(local);
554
555 ieee80211_recalc_ps(local, -1);
556
552 if (local->open_count == 0) { 557 if (local->open_count == 0) {
553 if (netif_running(local->mdev)) 558 if (netif_running(local->mdev))
554 dev_close(local->mdev); 559 dev_close(local->mdev);
555 560
556 if (local->ops->stop) 561 drv_stop(local);
557 local->ops->stop(local_to_hw(local));
558 562
559 ieee80211_led_radio(local, 0); 563 ieee80211_led_radio(local, 0);
560 564
@@ -567,8 +571,6 @@ static int ieee80211_stop(struct net_device *dev)
567 hw_reconf_flags = 0; 571 hw_reconf_flags = 0;
568 } 572 }
569 573
570 ieee80211_recalc_ps(local, -1);
571
572 /* do after stop to avoid reconfiguring when we stop anyway */ 574 /* do after stop to avoid reconfiguring when we stop anyway */
573 if (hw_reconf_flags) 575 if (hw_reconf_flags)
574 ieee80211_hw_config(local, hw_reconf_flags); 576 ieee80211_hw_config(local, hw_reconf_flags);
@@ -894,3 +896,73 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
894 unregister_netdevice(sdata->dev); 896 unregister_netdevice(sdata->dev);
895 } 897 }
896} 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}