aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-25 10:27:47 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:47 -0500
commit73651ee6396c499ccb59ebc84c9274db01ed026d (patch)
tree1d59027cbdaec732f3e1378770cbf7b42b48cd70 /net/mac80211/ieee80211.c
parentd0709a65181beb787ef3f58cfe45536a2bb254c8 (diff)
mac80211: split sta_info_add
sta_info_add() has two functions: allocating a station info structure and inserting it into the hash table/list. Splitting these two functions allows allocating with GFP_KERNEL in many places instead of GFP_ATOMIC which is now required by the RCU protection. Additionally, in many places RCU protection is now no longer needed at all because between sta_info_alloc() and sta_info_insert() the caller owns the structure. This fixes a few race conditions with setting initial flags and similar, but not all (see comments in ieee80211_sta.c and cfg.c). More documentation on the existing races will be in a follow-up patch. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211.c')
-rw-r--r--net/mac80211/ieee80211.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 85b1391375c0..22cba82a0c6f 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -899,6 +899,7 @@ int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
899 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 899 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
900 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 900 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
901 struct sta_info *sta; 901 struct sta_info *sta;
902 int err;
902 DECLARE_MAC_BUF(mac); 903 DECLARE_MAC_BUF(mac);
903 904
904 might_sleep(); 905 might_sleep();
@@ -906,16 +907,19 @@ int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
906 if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0) 907 if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
907 return 0; 908 return 0;
908 909
909 rcu_read_lock();
910
911 /* Create STA entry for the new peer */ 910 /* Create STA entry for the new peer */
912 sta = sta_info_add(sdata, remote_addr); 911 sta = sta_info_alloc(sdata, remote_addr, GFP_KERNEL);
913 if (IS_ERR(sta)) { 912 if (!sta)
914 rcu_read_unlock(); 913 return -ENOMEM;
915 return PTR_ERR(sta);
916 }
917 914
918 sta->flags |= WLAN_STA_AUTHORIZED; 915 sta->flags |= WLAN_STA_AUTHORIZED;
916 err = sta_info_insert(sta);
917 if (err) {
918 sta_info_destroy(sta);
919 return err;
920 }
921
922 rcu_read_lock();
919 923
920 /* Remove STA entry for the old peer */ 924 /* Remove STA entry for the old peer */
921 sta = sta_info_get(local, sdata->u.wds.remote_addr); 925 sta = sta_info_get(local, sdata->u.wds.remote_addr);