diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 100 |
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 | |||
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 | } | ||