aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ibss.c8
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/iface.c53
-rw-r--r--net/mac80211/mlme.c17
-rw-r--r--net/mac80211/scan.c2
-rw-r--r--net/mac80211/work.c8
6 files changed, 75 insertions, 16 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index c691780725a7..32af97108425 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -920,12 +920,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
920 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); 920 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
921 sdata->u.ibss.ssid_len = params->ssid_len; 921 sdata->u.ibss.ssid_len = params->ssid_len;
922 922
923 mutex_unlock(&sdata->u.ibss.mtx);
924
925 mutex_lock(&sdata->local->mtx);
923 ieee80211_recalc_idle(sdata->local); 926 ieee80211_recalc_idle(sdata->local);
927 mutex_unlock(&sdata->local->mtx);
924 928
925 ieee80211_queue_work(&sdata->local->hw, &sdata->work); 929 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
926 930
927 mutex_unlock(&sdata->u.ibss.mtx);
928
929 return 0; 931 return 0;
930} 932}
931 933
@@ -980,7 +982,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
980 982
981 mutex_unlock(&sdata->u.ibss.mtx); 983 mutex_unlock(&sdata->u.ibss.mtx);
982 984
985 mutex_lock(&local->mtx);
983 ieee80211_recalc_idle(sdata->local); 986 ieee80211_recalc_idle(sdata->local);
987 mutex_unlock(&local->mtx);
984 988
985 return 0; 989 return 0;
986} 990}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b44e03a02da9..98e783c6a363 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -497,6 +497,9 @@ struct ieee80211_sub_if_data {
497 */ 497 */
498 bool ht_opmode_valid; 498 bool ht_opmode_valid;
499 499
500 /* to detect idle changes */
501 bool old_idle;
502
500 /* Fragment table for host-based reassembly */ 503 /* Fragment table for host-based reassembly */
501 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; 504 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
502 unsigned int fragment_next; 505 unsigned int fragment_next;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c1008a9d7bfb..9459aeee0ddc 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -309,7 +309,9 @@ static int ieee80211_open(struct net_device *dev)
309 if (sdata->flags & IEEE80211_SDATA_PROMISC) 309 if (sdata->flags & IEEE80211_SDATA_PROMISC)
310 atomic_inc(&local->iff_promiscs); 310 atomic_inc(&local->iff_promiscs);
311 311
312 mutex_lock(&local->mtx);
312 hw_reconf_flags |= __ieee80211_recalc_idle(local); 313 hw_reconf_flags |= __ieee80211_recalc_idle(local);
314 mutex_unlock(&local->mtx);
313 315
314 local->open_count++; 316 local->open_count++;
315 if (hw_reconf_flags) { 317 if (hw_reconf_flags) {
@@ -516,7 +518,9 @@ static int ieee80211_stop(struct net_device *dev)
516 518
517 sdata->bss = NULL; 519 sdata->bss = NULL;
518 520
521 mutex_lock(&local->mtx);
519 hw_reconf_flags |= __ieee80211_recalc_idle(local); 522 hw_reconf_flags |= __ieee80211_recalc_idle(local);
523 mutex_unlock(&local->mtx);
520 524
521 ieee80211_recalc_ps(local, -1); 525 ieee80211_recalc_ps(local, -1);
522 526
@@ -1199,28 +1203,61 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1199{ 1203{
1200 struct ieee80211_sub_if_data *sdata; 1204 struct ieee80211_sub_if_data *sdata;
1201 int count = 0; 1205 int count = 0;
1206 bool working = false, scanning = false;
1207 struct ieee80211_work *wk;
1202 1208
1203 if (!list_empty(&local->work_list)) 1209#ifdef CONFIG_PROVE_LOCKING
1204 return ieee80211_idle_off(local, "working"); 1210 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
1205 1211 !lockdep_is_held(&local->iflist_mtx));
1206 if (local->scanning) 1212#endif
1207 return ieee80211_idle_off(local, "scanning"); 1213 lockdep_assert_held(&local->mtx);
1208 1214
1209 list_for_each_entry(sdata, &local->interfaces, list) { 1215 list_for_each_entry(sdata, &local->interfaces, list) {
1210 if (!ieee80211_sdata_running(sdata)) 1216 if (!ieee80211_sdata_running(sdata)) {
1217 sdata->vif.bss_conf.idle = true;
1211 continue; 1218 continue;
1219 }
1220
1221 sdata->old_idle = sdata->vif.bss_conf.idle;
1222
1212 /* do not count disabled managed interfaces */ 1223 /* do not count disabled managed interfaces */
1213 if (sdata->vif.type == NL80211_IFTYPE_STATION && 1224 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1214 !sdata->u.mgd.associated) 1225 !sdata->u.mgd.associated) {
1226 sdata->vif.bss_conf.idle = true;
1215 continue; 1227 continue;
1228 }
1216 /* do not count unused IBSS interfaces */ 1229 /* do not count unused IBSS interfaces */
1217 if (sdata->vif.type == NL80211_IFTYPE_ADHOC && 1230 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
1218 !sdata->u.ibss.ssid_len) 1231 !sdata->u.ibss.ssid_len) {
1232 sdata->vif.bss_conf.idle = true;
1219 continue; 1233 continue;
1234 }
1220 /* count everything else */ 1235 /* count everything else */
1221 count++; 1236 count++;
1222 } 1237 }
1223 1238
1239 list_for_each_entry(wk, &local->work_list, list) {
1240 working = true;
1241 wk->sdata->vif.bss_conf.idle = false;
1242 }
1243
1244 if (local->scan_sdata) {
1245 scanning = true;
1246 local->scan_sdata->vif.bss_conf.idle = false;
1247 }
1248
1249 list_for_each_entry(sdata, &local->interfaces, list) {
1250 if (sdata->old_idle == sdata->vif.bss_conf.idle)
1251 continue;
1252 if (!ieee80211_sdata_running(sdata))
1253 continue;
1254 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
1255 }
1256
1257 if (working)
1258 return ieee80211_idle_off(local, "working");
1259 if (scanning)
1260 return ieee80211_idle_off(local, "scanning");
1224 if (!count) 1261 if (!count)
1225 return ieee80211_idle_on(local); 1262 return ieee80211_idle_on(local);
1226 else 1263 else
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 17e9257a61d8..82e7cec5179c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1103,8 +1103,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1103 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); 1103 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
1104 1104
1105 ieee80211_set_disassoc(sdata, true); 1105 ieee80211_set_disassoc(sdata, true);
1106 ieee80211_recalc_idle(local);
1107 mutex_unlock(&ifmgd->mtx); 1106 mutex_unlock(&ifmgd->mtx);
1107
1108 mutex_lock(&local->mtx);
1109 ieee80211_recalc_idle(local);
1110 mutex_unlock(&local->mtx);
1108 /* 1111 /*
1109 * must be outside lock due to cfg80211, 1112 * must be outside lock due to cfg80211,
1110 * but that's not a problem. 1113 * but that's not a problem.
@@ -1173,7 +1176,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1173 sdata->name, bssid, reason_code); 1176 sdata->name, bssid, reason_code);
1174 1177
1175 ieee80211_set_disassoc(sdata, true); 1178 ieee80211_set_disassoc(sdata, true);
1179 mutex_lock(&sdata->local->mtx);
1176 ieee80211_recalc_idle(sdata->local); 1180 ieee80211_recalc_idle(sdata->local);
1181 mutex_unlock(&sdata->local->mtx);
1177 1182
1178 return RX_MGMT_CFG80211_DEAUTH; 1183 return RX_MGMT_CFG80211_DEAUTH;
1179} 1184}
@@ -1203,7 +1208,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1203 sdata->name, mgmt->sa, reason_code); 1208 sdata->name, mgmt->sa, reason_code);
1204 1209
1205 ieee80211_set_disassoc(sdata, true); 1210 ieee80211_set_disassoc(sdata, true);
1211 mutex_lock(&sdata->local->mtx);
1206 ieee80211_recalc_idle(sdata->local); 1212 ieee80211_recalc_idle(sdata->local);
1213 mutex_unlock(&sdata->local->mtx);
1207 return RX_MGMT_CFG80211_DISASSOC; 1214 return RX_MGMT_CFG80211_DISASSOC;
1208} 1215}
1209 1216
@@ -1840,8 +1847,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1840 " after %dms, disconnecting.\n", 1847 " after %dms, disconnecting.\n",
1841 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 1848 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1842 ieee80211_set_disassoc(sdata, true); 1849 ieee80211_set_disassoc(sdata, true);
1843 ieee80211_recalc_idle(local);
1844 mutex_unlock(&ifmgd->mtx); 1850 mutex_unlock(&ifmgd->mtx);
1851 mutex_lock(&local->mtx);
1852 ieee80211_recalc_idle(local);
1853 mutex_unlock(&local->mtx);
1845 /* 1854 /*
1846 * must be outside lock due to cfg80211, 1855 * must be outside lock due to cfg80211,
1847 * but that's not a problem. 1856 * but that's not a problem.
@@ -2319,7 +2328,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2319 if (assoc_bss) 2328 if (assoc_bss)
2320 sta_info_destroy_addr(sdata, bssid); 2329 sta_info_destroy_addr(sdata, bssid);
2321 2330
2331 mutex_lock(&sdata->local->mtx);
2322 ieee80211_recalc_idle(sdata->local); 2332 ieee80211_recalc_idle(sdata->local);
2333 mutex_unlock(&sdata->local->mtx);
2323 2334
2324 return 0; 2335 return 0;
2325} 2336}
@@ -2357,7 +2368,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2357 cookie, !req->local_state_change); 2368 cookie, !req->local_state_change);
2358 sta_info_destroy_addr(sdata, bssid); 2369 sta_info_destroy_addr(sdata, bssid);
2359 2370
2371 mutex_lock(&sdata->local->mtx);
2360 ieee80211_recalc_idle(sdata->local); 2372 ieee80211_recalc_idle(sdata->local);
2373 mutex_unlock(&sdata->local->mtx);
2361 2374
2362 return 0; 2375 return 0;
2363} 2376}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index f31f549733b1..31f233f7f51a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -304,7 +304,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
304 ieee80211_offchannel_return(local, true); 304 ieee80211_offchannel_return(local, true);
305 305
306 done: 306 done:
307 mutex_lock(&local->mtx);
307 ieee80211_recalc_idle(local); 308 ieee80211_recalc_idle(local);
309 mutex_unlock(&local->mtx);
308 ieee80211_mlme_notify_scan_completed(local); 310 ieee80211_mlme_notify_scan_completed(local);
309 ieee80211_ibss_notify_scan_completed(local); 311 ieee80211_ibss_notify_scan_completed(local);
310 ieee80211_mesh_notify_scan_completed(local); 312 ieee80211_mesh_notify_scan_completed(local);
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index b98af64f5862..ae344d1ba056 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -888,10 +888,10 @@ static void ieee80211_work_work(struct work_struct *work)
888 while ((skb = skb_dequeue(&local->work_skb_queue))) 888 while ((skb = skb_dequeue(&local->work_skb_queue)))
889 ieee80211_work_rx_queued_mgmt(local, skb); 889 ieee80211_work_rx_queued_mgmt(local, skb);
890 890
891 ieee80211_recalc_idle(local);
892
893 mutex_lock(&local->mtx); 891 mutex_lock(&local->mtx);
894 892
893 ieee80211_recalc_idle(local);
894
895 list_for_each_entry_safe(wk, tmp, &local->work_list, list) { 895 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
896 bool started = wk->started; 896 bool started = wk->started;
897 897
@@ -1001,10 +1001,10 @@ static void ieee80211_work_work(struct work_struct *work)
1001 &local->scan_work, 1001 &local->scan_work,
1002 round_jiffies_relative(0)); 1002 round_jiffies_relative(0));
1003 1003
1004 mutex_unlock(&local->mtx);
1005
1006 ieee80211_recalc_idle(local); 1004 ieee80211_recalc_idle(local);
1007 1005
1006 mutex_unlock(&local->mtx);
1007
1008 list_for_each_entry_safe(wk, tmp, &free_work, list) { 1008 list_for_each_entry_safe(wk, tmp, &free_work, list) {
1009 wk->done(wk, NULL); 1009 wk->done(wk, NULL);
1010 list_del(&wk->list); 1010 list_del(&wk->list);