diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 117 |
1 files changed, 94 insertions, 23 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 91e8e1bacaaa..b7c8a4484298 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,14 +165,12 @@ 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 */ |
173 | hw_reconf_flags = ~0; | 172 | hw_reconf_flags = ~0; |
174 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | 173 | ieee80211_led_radio(local, true); |
175 | } | 174 | } |
176 | 175 | ||
177 | /* | 176 | /* |
@@ -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 | ||
@@ -235,17 +234,13 @@ static int ieee80211_open(struct net_device *dev) | |||
235 | netif_addr_unlock_bh(local->mdev); | 234 | netif_addr_unlock_bh(local->mdev); |
236 | break; | 235 | break; |
237 | case NL80211_IFTYPE_STATION: | 236 | case NL80211_IFTYPE_STATION: |
238 | case NL80211_IFTYPE_ADHOC: | 237 | sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
239 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
240 | sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
241 | else | ||
242 | sdata->u.ibss.flags &= ~IEEE80211_IBSS_PREV_BSSID_SET; | ||
243 | /* fall through */ | 238 | /* fall through */ |
244 | default: | 239 | default: |
245 | conf.vif = &sdata->vif; | 240 | conf.vif = &sdata->vif; |
246 | conf.type = sdata->vif.type; | 241 | conf.type = sdata->vif.type; |
247 | conf.mac_addr = dev->dev_addr; | 242 | conf.mac_addr = dev->dev_addr; |
248 | res = local->ops->add_interface(local_to_hw(local), &conf); | 243 | res = drv_add_interface(local, &conf); |
249 | if (res) | 244 | if (res) |
250 | goto err_stop; | 245 | goto err_stop; |
251 | 246 | ||
@@ -306,6 +301,8 @@ static int ieee80211_open(struct net_device *dev) | |||
306 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 301 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
307 | atomic_inc(&local->iff_promiscs); | 302 | atomic_inc(&local->iff_promiscs); |
308 | 303 | ||
304 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
305 | |||
309 | local->open_count++; | 306 | local->open_count++; |
310 | if (hw_reconf_flags) { | 307 | if (hw_reconf_flags) { |
311 | ieee80211_hw_config(local, hw_reconf_flags); | 308 | ieee80211_hw_config(local, hw_reconf_flags); |
@@ -317,6 +314,8 @@ static int ieee80211_open(struct net_device *dev) | |||
317 | ieee80211_set_wmm_default(sdata); | 314 | ieee80211_set_wmm_default(sdata); |
318 | } | 315 | } |
319 | 316 | ||
317 | ieee80211_recalc_ps(local, -1); | ||
318 | |||
320 | /* | 319 | /* |
321 | * ieee80211_sta_work is disabled while network interface | 320 | * ieee80211_sta_work is disabled while network interface |
322 | * is down. Therefore, some configuration changes may not | 321 | * is down. Therefore, some configuration changes may not |
@@ -325,17 +324,15 @@ static int ieee80211_open(struct net_device *dev) | |||
325 | */ | 324 | */ |
326 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 325 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
327 | queue_work(local->hw.workqueue, &sdata->u.mgd.work); | 326 | queue_work(local->hw.workqueue, &sdata->u.mgd.work); |
328 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
329 | queue_work(local->hw.workqueue, &sdata->u.ibss.work); | ||
330 | 327 | ||
331 | netif_tx_start_all_queues(dev); | 328 | netif_tx_start_all_queues(dev); |
332 | 329 | ||
333 | return 0; | 330 | return 0; |
334 | err_del_interface: | 331 | err_del_interface: |
335 | local->ops->remove_interface(local_to_hw(local), &conf); | 332 | drv_remove_interface(local, &conf); |
336 | err_stop: | 333 | err_stop: |
337 | if (!local->open_count && local->ops->stop) | 334 | if (!local->open_count) |
338 | local->ops->stop(local_to_hw(local)); | 335 | drv_stop(local); |
339 | err_del_bss: | 336 | err_del_bss: |
340 | sdata->bss = NULL; | 337 | sdata->bss = NULL; |
341 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 338 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -497,7 +494,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
497 | /* fall through */ | 494 | /* fall through */ |
498 | case NL80211_IFTYPE_ADHOC: | 495 | case NL80211_IFTYPE_ADHOC: |
499 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 496 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
500 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); | ||
501 | del_timer_sync(&sdata->u.ibss.timer); | 497 | del_timer_sync(&sdata->u.ibss.timer); |
502 | cancel_work_sync(&sdata->u.ibss.work); | 498 | cancel_work_sync(&sdata->u.ibss.work); |
503 | synchronize_rcu(); | 499 | synchronize_rcu(); |
@@ -549,19 +545,22 @@ static int ieee80211_stop(struct net_device *dev) | |||
549 | conf.mac_addr = dev->dev_addr; | 545 | conf.mac_addr = dev->dev_addr; |
550 | /* disable all keys for as long as this netdev is down */ | 546 | /* disable all keys for as long as this netdev is down */ |
551 | ieee80211_disable_keys(sdata); | 547 | ieee80211_disable_keys(sdata); |
552 | local->ops->remove_interface(local_to_hw(local), &conf); | 548 | drv_remove_interface(local, &conf); |
553 | } | 549 | } |
554 | 550 | ||
555 | sdata->bss = NULL; | 551 | sdata->bss = NULL; |
556 | 552 | ||
553 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
554 | |||
555 | ieee80211_recalc_ps(local, -1); | ||
556 | |||
557 | if (local->open_count == 0) { | 557 | if (local->open_count == 0) { |
558 | if (netif_running(local->mdev)) | 558 | if (netif_running(local->mdev)) |
559 | dev_close(local->mdev); | 559 | dev_close(local->mdev); |
560 | 560 | ||
561 | if (local->ops->stop) | 561 | drv_stop(local); |
562 | local->ops->stop(local_to_hw(local)); | ||
563 | 562 | ||
564 | ieee80211_led_radio(local, 0); | 563 | ieee80211_led_radio(local, false); |
565 | 564 | ||
566 | flush_workqueue(local->hw.workqueue); | 565 | flush_workqueue(local->hw.workqueue); |
567 | 566 | ||
@@ -649,7 +648,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
649 | mesh_rmc_free(sdata); | 648 | mesh_rmc_free(sdata); |
650 | break; | 649 | break; |
651 | case NL80211_IFTYPE_ADHOC: | 650 | case NL80211_IFTYPE_ADHOC: |
652 | kfree_skb(sdata->u.ibss.probe_resp); | 651 | if (WARN_ON(sdata->u.ibss.presp)) |
652 | kfree_skb(sdata->u.ibss.presp); | ||
653 | break; | 653 | break; |
654 | case NL80211_IFTYPE_STATION: | 654 | case NL80211_IFTYPE_STATION: |
655 | kfree(sdata->u.mgd.extra_ie); | 655 | kfree(sdata->u.mgd.extra_ie); |
@@ -896,3 +896,74 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
896 | unregister_netdevice(sdata->dev); | 896 | unregister_netdevice(sdata->dev); |
897 | } | 897 | } |
898 | } | 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 | if (chg) | ||
968 | ieee80211_hw_config(local, chg); | ||
969 | } | ||