aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c5
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c78
-rw-r--r--net/mac80211/mlme.c11
-rw-r--r--net/mac80211/scan.c17
5 files changed, 101 insertions, 12 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index a8e23232267e..aa537681f87c 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -862,6 +862,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
862 862
863 sdata->u.ibss.ssid_len = params->ssid_len; 863 sdata->u.ibss.ssid_len = params->ssid_len;
864 864
865 ieee80211_recalc_idle(sdata->local);
866
865 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); 867 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
866 queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); 868 queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work);
867 869
@@ -889,6 +891,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
889 891
890 skb_queue_purge(&sdata->u.ibss.skb_queue); 892 skb_queue_purge(&sdata->u.ibss.skb_queue);
891 memset(sdata->u.ibss.bssid, 0, ETH_ALEN); 893 memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
894 sdata->u.ibss.ssid_len = 0;
895
896 ieee80211_recalc_idle(sdata->local);
892 897
893 return 0; 898 return 0;
894} 899}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 236ea098bb6c..03e0d22603c8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -985,6 +985,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
985 enum nl80211_iftype type); 985 enum nl80211_iftype type);
986void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); 986void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
987void ieee80211_remove_interfaces(struct ieee80211_local *local); 987void ieee80211_remove_interfaces(struct ieee80211_local *local);
988u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
989void ieee80211_recalc_idle(struct ieee80211_local *local);
988 990
989/* tx handling */ 991/* tx handling */
990void ieee80211_clear_tx_pending(struct ieee80211_local *local); 992void ieee80211_clear_tx_pending(struct ieee80211_local *local);
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}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2ded4766d014..5509c5aa6beb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -890,6 +890,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
890 printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", 890 printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
891 sdata->dev->name, ifmgd->bssid); 891 sdata->dev->name, ifmgd->bssid);
892 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 892 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
893 ieee80211_recalc_idle(local);
893 cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); 894 cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
894 895
895 /* 896 /*
@@ -938,6 +939,7 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
938 " timed out\n", 939 " timed out\n",
939 sdata->dev->name, ifmgd->bssid); 940 sdata->dev->name, ifmgd->bssid);
940 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 941 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
942 ieee80211_recalc_idle(local);
941 cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); 943 cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
942 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 944 ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
943 sdata->local->hw.conf.channel->center_freq, 945 sdata->local->hw.conf.channel->center_freq,
@@ -1041,6 +1043,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1041 1043
1042 rcu_read_unlock(); 1044 rcu_read_unlock();
1043 1045
1046 ieee80211_recalc_idle(local);
1047
1044 /* channel(_type) changes are handled by ieee80211_hw_config */ 1048 /* channel(_type) changes are handled by ieee80211_hw_config */
1045 local->oper_channel_type = NL80211_CHAN_NO_HT; 1049 local->oper_channel_type = NL80211_CHAN_NO_HT;
1046 1050
@@ -1121,6 +1125,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
1121 " timed out\n", 1125 " timed out\n",
1122 sdata->dev->name, ifmgd->bssid); 1126 sdata->dev->name, ifmgd->bssid);
1123 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 1127 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1128 ieee80211_recalc_idle(local);
1124 cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid); 1129 cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid);
1125 ieee80211_rx_bss_remove(sdata, ifmgd->bssid, 1130 ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
1126 sdata->local->hw.conf.channel->center_freq, 1131 sdata->local->hw.conf.channel->center_freq,
@@ -1141,6 +1146,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
1141 printk(KERN_DEBUG "%s: mismatch in privacy configuration and " 1146 printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
1142 "mixed-cell disabled - abort association\n", sdata->dev->name); 1147 "mixed-cell disabled - abort association\n", sdata->dev->name);
1143 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 1148 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1149 ieee80211_recalc_idle(local);
1144 return; 1150 return;
1145 } 1151 }
1146 1152
@@ -1279,6 +1285,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
1279 if (ifmgd->flags & IEEE80211_STA_EXT_SME) { 1285 if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
1280 /* Wait for SME to request association */ 1286 /* Wait for SME to request association */
1281 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 1287 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1288 ieee80211_recalc_idle(sdata->local);
1282 } else 1289 } else
1283 ieee80211_associate(sdata); 1290 ieee80211_associate(sdata);
1284} 1291}
@@ -1515,6 +1522,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1515 if (ifmgd->flags & IEEE80211_STA_EXT_SME) { 1522 if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
1516 /* Wait for SME to decide what to do next */ 1523 /* Wait for SME to decide what to do next */
1517 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 1524 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1525 ieee80211_recalc_idle(local);
1518 } 1526 }
1519 return; 1527 return;
1520 } 1528 }
@@ -2083,6 +2091,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
2083 } else { 2091 } else {
2084 ifmgd->assoc_scan_tries = 0; 2092 ifmgd->assoc_scan_tries = 0;
2085 ifmgd->state = IEEE80211_STA_MLME_DISABLED; 2093 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
2094 ieee80211_recalc_idle(local);
2086 } 2095 }
2087 } 2096 }
2088 return -1; 2097 return -1;
@@ -2126,6 +2135,8 @@ static void ieee80211_sta_work(struct work_struct *work)
2126 } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request)) 2135 } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request))
2127 return; 2136 return;
2128 2137
2138 ieee80211_recalc_idle(local);
2139
2129 switch (ifmgd->state) { 2140 switch (ifmgd->state) {
2130 case IEEE80211_STA_MLME_DISABLED: 2141 case IEEE80211_STA_MLME_DISABLED:
2131 break; 2142 break;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 127bd54e0e38..c99ef8d04d3d 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -302,17 +302,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
302 /* we only have to protect scan_req and hw/sw scan */ 302 /* we only have to protect scan_req and hw/sw scan */
303 mutex_unlock(&local->scan_mtx); 303 mutex_unlock(&local->scan_mtx);
304 304
305 if (was_hw_scan) {
306 /*
307 * Somebody might have requested channel change during scan
308 * that we won't have acted upon, try now. ieee80211_hw_config
309 * will set the flag based on actual changes.
310 */
311 ieee80211_hw_config(local, 0);
312 goto done;
313 }
314
315 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 305 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
306 if (was_hw_scan)
307 goto done;
316 308
317 netif_tx_lock_bh(local->mdev); 309 netif_tx_lock_bh(local->mdev);
318 netif_addr_lock(local->mdev); 310 netif_addr_lock(local->mdev);
@@ -351,6 +343,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
351 mutex_unlock(&local->iflist_mtx); 343 mutex_unlock(&local->iflist_mtx);
352 344
353 done: 345 done:
346 ieee80211_recalc_idle(local);
354 ieee80211_mlme_notify_scan_completed(local); 347 ieee80211_mlme_notify_scan_completed(local);
355 ieee80211_ibss_notify_scan_completed(local); 348 ieee80211_ibss_notify_scan_completed(local);
356 ieee80211_mesh_notify_scan_completed(local); 349 ieee80211_mesh_notify_scan_completed(local);
@@ -471,6 +464,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
471 * dependency, so that the scan completed calls 464 * dependency, so that the scan completed calls
472 * have more locking freedom. 465 * have more locking freedom.
473 */ 466 */
467
468 ieee80211_recalc_idle(local);
474 mutex_unlock(&local->scan_mtx); 469 mutex_unlock(&local->scan_mtx);
475 470
476 if (local->ops->hw_scan) 471 if (local->ops->hw_scan)
@@ -487,6 +482,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
487 } else 482 } else
488 local->sw_scanning = false; 483 local->sw_scanning = false;
489 484
485 ieee80211_recalc_idle(local);
486
490 local->scan_req = NULL; 487 local->scan_req = NULL;
491 local->scan_sdata = NULL; 488 local->scan_sdata = NULL;
492 } 489 }