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.c117
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
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 if (chg)
968 ieee80211_hw_config(local, chg);
969}