diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-02-25 10:27:47 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-06 15:30:47 -0500 |
commit | 73651ee6396c499ccb59ebc84c9274db01ed026d (patch) | |
tree | 1d59027cbdaec732f3e1378770cbf7b42b48cd70 /net/mac80211/ieee80211.c | |
parent | d0709a65181beb787ef3f58cfe45536a2bb254c8 (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.c | 18 |
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); |