diff options
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 123 |
1 files changed, 85 insertions, 38 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 9f933aeca719..a3e96eb59eb0 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/wireless.h> | 24 | #include <linux/wireless.h> |
25 | #include <linux/random.h> | 25 | #include <linux/random.h> |
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | #include <linux/rtnetlink.h> | ||
27 | #include <net/iw_handler.h> | 28 | #include <net/iw_handler.h> |
28 | #include <asm/types.h> | 29 | #include <asm/types.h> |
29 | 30 | ||
@@ -845,6 +846,8 @@ static void ieee80211_associated(struct net_device *dev, | |||
845 | 846 | ||
846 | ifsta->state = IEEE80211_ASSOCIATED; | 847 | ifsta->state = IEEE80211_ASSOCIATED; |
847 | 848 | ||
849 | rcu_read_lock(); | ||
850 | |||
848 | sta = sta_info_get(local, ifsta->bssid); | 851 | sta = sta_info_get(local, ifsta->bssid); |
849 | if (!sta) { | 852 | if (!sta) { |
850 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", | 853 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", |
@@ -860,7 +863,7 @@ static void ieee80211_associated(struct net_device *dev, | |||
860 | "range\n", | 863 | "range\n", |
861 | dev->name, print_mac(mac, ifsta->bssid)); | 864 | dev->name, print_mac(mac, ifsta->bssid)); |
862 | disassoc = 1; | 865 | disassoc = 1; |
863 | sta_info_free(sta); | 866 | sta_info_unlink(&sta); |
864 | } else | 867 | } else |
865 | ieee80211_send_probe_req(dev, ifsta->bssid, | 868 | ieee80211_send_probe_req(dev, ifsta->bssid, |
866 | local->scan_ssid, | 869 | local->scan_ssid, |
@@ -876,8 +879,17 @@ static void ieee80211_associated(struct net_device *dev, | |||
876 | ifsta->ssid_len); | 879 | ifsta->ssid_len); |
877 | } | 880 | } |
878 | } | 881 | } |
879 | sta_info_put(sta); | ||
880 | } | 882 | } |
883 | |||
884 | rcu_read_unlock(); | ||
885 | |||
886 | if (disassoc && sta) { | ||
887 | synchronize_rcu(); | ||
888 | rtnl_lock(); | ||
889 | sta_info_destroy(sta); | ||
890 | rtnl_unlock(); | ||
891 | } | ||
892 | |||
881 | if (disassoc) { | 893 | if (disassoc) { |
882 | ifsta->state = IEEE80211_DISABLED; | 894 | ifsta->state = IEEE80211_DISABLED; |
883 | ieee80211_set_associated(dev, ifsta, 0); | 895 | ieee80211_set_associated(dev, ifsta, 0); |
@@ -1103,9 +1115,13 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1103 | int ret = -EOPNOTSUPP; | 1115 | int ret = -EOPNOTSUPP; |
1104 | DECLARE_MAC_BUF(mac); | 1116 | DECLARE_MAC_BUF(mac); |
1105 | 1117 | ||
1118 | rcu_read_lock(); | ||
1119 | |||
1106 | sta = sta_info_get(local, mgmt->sa); | 1120 | sta = sta_info_get(local, mgmt->sa); |
1107 | if (!sta) | 1121 | if (!sta) { |
1122 | rcu_read_unlock(); | ||
1108 | return; | 1123 | return; |
1124 | } | ||
1109 | 1125 | ||
1110 | /* extract session parameters from addba request frame */ | 1126 | /* extract session parameters from addba request frame */ |
1111 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | 1127 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; |
@@ -1197,9 +1213,9 @@ end: | |||
1197 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1213 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); |
1198 | 1214 | ||
1199 | end_no_lock: | 1215 | end_no_lock: |
1200 | ieee80211_send_addba_resp(sta->dev, sta->addr, tid, dialog_token, | 1216 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, |
1201 | status, 1, buf_size, timeout); | 1217 | dialog_token, status, 1, buf_size, timeout); |
1202 | sta_info_put(sta); | 1218 | rcu_read_unlock(); |
1203 | } | 1219 | } |
1204 | 1220 | ||
1205 | static void ieee80211_sta_process_addba_resp(struct net_device *dev, | 1221 | static void ieee80211_sta_process_addba_resp(struct net_device *dev, |
@@ -1213,9 +1229,13 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1213 | u16 tid; | 1229 | u16 tid; |
1214 | u8 *state; | 1230 | u8 *state; |
1215 | 1231 | ||
1232 | rcu_read_lock(); | ||
1233 | |||
1216 | sta = sta_info_get(local, mgmt->sa); | 1234 | sta = sta_info_get(local, mgmt->sa); |
1217 | if (!sta) | 1235 | if (!sta) { |
1236 | rcu_read_unlock(); | ||
1218 | return; | 1237 | return; |
1238 | } | ||
1219 | 1239 | ||
1220 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 1240 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
1221 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 1241 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
@@ -1230,7 +1250,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1230 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1250 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1231 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 1251 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
1232 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1252 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
1233 | sta_info_put(sta); | 1253 | rcu_read_unlock(); |
1234 | return; | 1254 | return; |
1235 | } | 1255 | } |
1236 | 1256 | ||
@@ -1244,7 +1264,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1244 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1264 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1245 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | 1265 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" |
1246 | "%d\n", *state); | 1266 | "%d\n", *state); |
1247 | sta_info_put(sta); | 1267 | rcu_read_unlock(); |
1248 | return; | 1268 | return; |
1249 | } | 1269 | } |
1250 | 1270 | ||
@@ -1271,7 +1291,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1271 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 1291 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, |
1272 | WLAN_BACK_INITIATOR); | 1292 | WLAN_BACK_INITIATOR); |
1273 | } | 1293 | } |
1274 | sta_info_put(sta); | 1294 | rcu_read_unlock(); |
1275 | } | 1295 | } |
1276 | 1296 | ||
1277 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | 1297 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, |
@@ -1326,16 +1346,20 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1326 | struct sta_info *sta; | 1346 | struct sta_info *sta; |
1327 | int ret, i; | 1347 | int ret, i; |
1328 | 1348 | ||
1349 | rcu_read_lock(); | ||
1350 | |||
1329 | sta = sta_info_get(local, ra); | 1351 | sta = sta_info_get(local, ra); |
1330 | if (!sta) | 1352 | if (!sta) { |
1353 | rcu_read_unlock(); | ||
1331 | return; | 1354 | return; |
1355 | } | ||
1332 | 1356 | ||
1333 | /* check if TID is in operational state */ | 1357 | /* check if TID is in operational state */ |
1334 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1358 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); |
1335 | if (sta->ampdu_mlme.tid_rx[tid].state | 1359 | if (sta->ampdu_mlme.tid_rx[tid].state |
1336 | != HT_AGG_STATE_OPERATIONAL) { | 1360 | != HT_AGG_STATE_OPERATIONAL) { |
1337 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1361 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); |
1338 | sta_info_put(sta); | 1362 | rcu_read_unlock(); |
1339 | return; | 1363 | return; |
1340 | } | 1364 | } |
1341 | sta->ampdu_mlme.tid_rx[tid].state = | 1365 | sta->ampdu_mlme.tid_rx[tid].state = |
@@ -1374,7 +1398,7 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1374 | kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf); | 1398 | kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf); |
1375 | 1399 | ||
1376 | sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE; | 1400 | sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE; |
1377 | sta_info_put(sta); | 1401 | rcu_read_unlock(); |
1378 | } | 1402 | } |
1379 | 1403 | ||
1380 | 1404 | ||
@@ -1387,9 +1411,13 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1387 | u16 initiator; | 1411 | u16 initiator; |
1388 | DECLARE_MAC_BUF(mac); | 1412 | DECLARE_MAC_BUF(mac); |
1389 | 1413 | ||
1414 | rcu_read_lock(); | ||
1415 | |||
1390 | sta = sta_info_get(local, mgmt->sa); | 1416 | sta = sta_info_get(local, mgmt->sa); |
1391 | if (!sta) | 1417 | if (!sta) { |
1418 | rcu_read_unlock(); | ||
1392 | return; | 1419 | return; |
1420 | } | ||
1393 | 1421 | ||
1394 | params = le16_to_cpu(mgmt->u.action.u.delba.params); | 1422 | params = le16_to_cpu(mgmt->u.action.u.delba.params); |
1395 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; | 1423 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; |
@@ -1414,7 +1442,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1414 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | 1442 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, |
1415 | WLAN_BACK_RECIPIENT); | 1443 | WLAN_BACK_RECIPIENT); |
1416 | } | 1444 | } |
1417 | sta_info_put(sta); | 1445 | rcu_read_unlock(); |
1418 | } | 1446 | } |
1419 | 1447 | ||
1420 | /* | 1448 | /* |
@@ -1437,9 +1465,13 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1437 | struct sta_info *sta; | 1465 | struct sta_info *sta; |
1438 | u8 *state; | 1466 | u8 *state; |
1439 | 1467 | ||
1468 | rcu_read_lock(); | ||
1469 | |||
1440 | sta = sta_info_get(local, temp_sta->addr); | 1470 | sta = sta_info_get(local, temp_sta->addr); |
1441 | if (!sta) | 1471 | if (!sta) { |
1472 | rcu_read_unlock(); | ||
1442 | return; | 1473 | return; |
1474 | } | ||
1443 | 1475 | ||
1444 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 1476 | state = &sta->ampdu_mlme.tid_tx[tid].state; |
1445 | /* check if the TID waits for addBA response */ | 1477 | /* check if the TID waits for addBA response */ |
@@ -1461,7 +1493,7 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1461 | WLAN_BACK_INITIATOR); | 1493 | WLAN_BACK_INITIATOR); |
1462 | 1494 | ||
1463 | timer_expired_exit: | 1495 | timer_expired_exit: |
1464 | sta_info_put(sta); | 1496 | rcu_read_unlock(); |
1465 | } | 1497 | } |
1466 | 1498 | ||
1467 | /* | 1499 | /* |
@@ -1481,8 +1513,8 @@ void sta_rx_agg_session_timer_expired(unsigned long data) | |||
1481 | timer_to_tid[0]); | 1513 | timer_to_tid[0]); |
1482 | 1514 | ||
1483 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 1515 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
1484 | ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr, (u16)*ptid, | 1516 | ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, |
1485 | WLAN_BACK_TIMER, | 1517 | (u16)*ptid, WLAN_BACK_TIMER, |
1486 | WLAN_REASON_QSTA_TIMEOUT); | 1518 | WLAN_REASON_QSTA_TIMEOUT); |
1487 | } | 1519 | } |
1488 | 1520 | ||
@@ -1791,14 +1823,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1791 | if (ifsta->assocresp_ies) | 1823 | if (ifsta->assocresp_ies) |
1792 | memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len); | 1824 | memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len); |
1793 | 1825 | ||
1826 | rcu_read_lock(); | ||
1827 | |||
1794 | /* Add STA entry for the AP */ | 1828 | /* Add STA entry for the AP */ |
1795 | sta = sta_info_get(local, ifsta->bssid); | 1829 | sta = sta_info_get(local, ifsta->bssid); |
1796 | if (!sta) { | 1830 | if (!sta) { |
1797 | struct ieee80211_sta_bss *bss; | 1831 | struct ieee80211_sta_bss *bss; |
1798 | sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL); | 1832 | |
1833 | sta = sta_info_add(sdata, ifsta->bssid); | ||
1799 | if (IS_ERR(sta)) { | 1834 | if (IS_ERR(sta)) { |
1800 | printk(KERN_DEBUG "%s: failed to add STA entry for the" | 1835 | printk(KERN_DEBUG "%s: failed to add STA entry for the" |
1801 | " AP (error %ld)\n", dev->name, PTR_ERR(sta)); | 1836 | " AP (error %ld)\n", dev->name, PTR_ERR(sta)); |
1837 | rcu_read_unlock(); | ||
1802 | return; | 1838 | return; |
1803 | } | 1839 | } |
1804 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 1840 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, |
@@ -1812,7 +1848,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1812 | } | 1848 | } |
1813 | } | 1849 | } |
1814 | 1850 | ||
1815 | sta->dev = dev; | ||
1816 | sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | | 1851 | sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | |
1817 | WLAN_STA_AUTHORIZED; | 1852 | WLAN_STA_AUTHORIZED; |
1818 | 1853 | ||
@@ -1883,7 +1918,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1883 | bss_conf->aid = aid; | 1918 | bss_conf->aid = aid; |
1884 | ieee80211_set_associated(dev, ifsta, 1); | 1919 | ieee80211_set_associated(dev, ifsta, 1); |
1885 | 1920 | ||
1886 | sta_info_put(sta); | 1921 | rcu_read_unlock(); |
1887 | 1922 | ||
1888 | ieee80211_associated(dev, ifsta); | 1923 | ieee80211_associated(dev, ifsta); |
1889 | } | 1924 | } |
@@ -2329,6 +2364,8 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2329 | mesh_peer_accepts_plinks(&elems, dev)); | 2364 | mesh_peer_accepts_plinks(&elems, dev)); |
2330 | } | 2365 | } |
2331 | 2366 | ||
2367 | rcu_read_lock(); | ||
2368 | |||
2332 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && | 2369 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && |
2333 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && | 2370 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && |
2334 | (sta = sta_info_get(local, mgmt->sa))) { | 2371 | (sta = sta_info_get(local, mgmt->sa))) { |
@@ -2354,9 +2391,10 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2354 | (unsigned long long) supp_rates, | 2391 | (unsigned long long) supp_rates, |
2355 | (unsigned long long) sta->supp_rates[rx_status->band]); | 2392 | (unsigned long long) sta->supp_rates[rx_status->band]); |
2356 | } | 2393 | } |
2357 | sta_info_put(sta); | ||
2358 | } | 2394 | } |
2359 | 2395 | ||
2396 | rcu_read_unlock(); | ||
2397 | |||
2360 | if (elems.ds_params && elems.ds_params_len == 1) | 2398 | if (elems.ds_params && elems.ds_params_len == 1) |
2361 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | 2399 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); |
2362 | else | 2400 | else |
@@ -2550,8 +2588,10 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2550 | "local TSF - IBSS merge with BSSID %s\n", | 2588 | "local TSF - IBSS merge with BSSID %s\n", |
2551 | dev->name, print_mac(mac, mgmt->bssid)); | 2589 | dev->name, print_mac(mac, mgmt->bssid)); |
2552 | ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); | 2590 | ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); |
2591 | rcu_read_lock(); | ||
2553 | ieee80211_ibss_add_sta(dev, NULL, | 2592 | ieee80211_ibss_add_sta(dev, NULL, |
2554 | mgmt->bssid, mgmt->sa); | 2593 | mgmt->bssid, mgmt->sa); |
2594 | rcu_read_unlock(); | ||
2555 | } | 2595 | } |
2556 | } | 2596 | } |
2557 | 2597 | ||
@@ -2893,17 +2933,20 @@ static int ieee80211_sta_active_ibss(struct net_device *dev) | |||
2893 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2933 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
2894 | int active = 0; | 2934 | int active = 0; |
2895 | struct sta_info *sta; | 2935 | struct sta_info *sta; |
2936 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2896 | 2937 | ||
2897 | read_lock_bh(&local->sta_lock); | 2938 | rcu_read_lock(); |
2898 | list_for_each_entry(sta, &local->sta_list, list) { | 2939 | |
2899 | if (sta->dev == dev && | 2940 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
2941 | if (sta->sdata == sdata && | ||
2900 | time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, | 2942 | time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, |
2901 | jiffies)) { | 2943 | jiffies)) { |
2902 | active++; | 2944 | active++; |
2903 | break; | 2945 | break; |
2904 | } | 2946 | } |
2905 | } | 2947 | } |
2906 | read_unlock_bh(&local->sta_lock); | 2948 | |
2949 | rcu_read_unlock(); | ||
2907 | 2950 | ||
2908 | return active; | 2951 | return active; |
2909 | } | 2952 | } |
@@ -2915,22 +2958,25 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) | |||
2915 | struct sta_info *sta, *tmp; | 2958 | struct sta_info *sta, *tmp; |
2916 | LIST_HEAD(tmp_list); | 2959 | LIST_HEAD(tmp_list); |
2917 | DECLARE_MAC_BUF(mac); | 2960 | DECLARE_MAC_BUF(mac); |
2961 | unsigned long flags; | ||
2918 | 2962 | ||
2919 | write_lock_bh(&local->sta_lock); | 2963 | spin_lock_irqsave(&local->sta_lock, flags); |
2920 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | 2964 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) |
2921 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 2965 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
2922 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | 2966 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", |
2923 | dev->name, print_mac(mac, sta->addr)); | 2967 | dev->name, print_mac(mac, sta->addr)); |
2924 | __sta_info_get(sta); | 2968 | sta_info_unlink(&sta); |
2925 | sta_info_remove(sta); | 2969 | if (sta) |
2926 | list_add(&sta->list, &tmp_list); | 2970 | list_add(&sta->list, &tmp_list); |
2927 | } | 2971 | } |
2928 | write_unlock_bh(&local->sta_lock); | 2972 | spin_unlock_irqrestore(&local->sta_lock, flags); |
2929 | 2973 | ||
2930 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) { | 2974 | synchronize_rcu(); |
2931 | sta_info_free(sta); | 2975 | |
2932 | sta_info_put(sta); | 2976 | rtnl_lock(); |
2933 | } | 2977 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) |
2978 | sta_info_destroy(sta); | ||
2979 | rtnl_unlock(); | ||
2934 | } | 2980 | } |
2935 | 2981 | ||
2936 | 2982 | ||
@@ -3977,6 +4023,7 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | |||
3977 | } | 4023 | } |
3978 | 4024 | ||
3979 | 4025 | ||
4026 | /* must be called under RCU read lock */ | ||
3980 | struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, | 4027 | struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, |
3981 | struct sk_buff *skb, u8 *bssid, | 4028 | struct sk_buff *skb, u8 *bssid, |
3982 | u8 *addr) | 4029 | u8 *addr) |
@@ -3999,7 +4046,7 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, | |||
3999 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", | 4046 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", |
4000 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); | 4047 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); |
4001 | 4048 | ||
4002 | sta = sta_info_add(local, dev, addr, GFP_ATOMIC); | 4049 | sta = sta_info_add(sdata, addr); |
4003 | if (IS_ERR(sta)) | 4050 | if (IS_ERR(sta)) |
4004 | return NULL; | 4051 | return NULL; |
4005 | 4052 | ||
@@ -4010,7 +4057,7 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, | |||
4010 | 4057 | ||
4011 | rate_control_rate_init(sta, local); | 4058 | rate_control_rate_init(sta, local); |
4012 | 4059 | ||
4013 | return sta; /* caller will call sta_info_put() */ | 4060 | return sta; |
4014 | } | 4061 | } |
4015 | 4062 | ||
4016 | 4063 | ||