aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.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/cfg.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/cfg.c')
-rw-r--r--net/mac80211/cfg.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e9ba6fcc0e45..6263cfc148c0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -571,6 +571,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
571 struct ieee80211_supported_band *sband; 571 struct ieee80211_supported_band *sband;
572 struct ieee80211_sub_if_data *sdata = sta->sdata; 572 struct ieee80211_sub_if_data *sdata = sta->sdata;
573 573
574 /*
575 * FIXME: updating the flags is racy when this function is
576 * called from ieee80211_change_station(), this will
577 * be resolved in a future patch.
578 */
579
574 if (params->station_flags & STATION_FLAG_CHANGED) { 580 if (params->station_flags & STATION_FLAG_CHANGED) {
575 sta->flags &= ~WLAN_STA_AUTHORIZED; 581 sta->flags &= ~WLAN_STA_AUTHORIZED;
576 if (params->station_flags & STATION_FLAG_AUTHORIZED) 582 if (params->station_flags & STATION_FLAG_AUTHORIZED)
@@ -585,6 +591,13 @@ static void sta_apply_parameters(struct ieee80211_local *local,
585 sta->flags |= WLAN_STA_WME; 591 sta->flags |= WLAN_STA_WME;
586 } 592 }
587 593
594 /*
595 * FIXME: updating the following information is racy when this
596 * function is called from ieee80211_change_station().
597 * However, all this information should be static so
598 * maybe we should just reject attemps to change it.
599 */
600
588 if (params->aid) { 601 if (params->aid) {
589 sta->aid = params->aid; 602 sta->aid = params->aid;
590 if (sta->aid > IEEE80211_MAX_AID) 603 if (sta->aid > IEEE80211_MAX_AID)
@@ -626,6 +639,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
626 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 639 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
627 struct sta_info *sta; 640 struct sta_info *sta;
628 struct ieee80211_sub_if_data *sdata; 641 struct ieee80211_sub_if_data *sdata;
642 int err;
629 643
630 /* Prevent a race with changing the rate control algorithm */ 644 /* Prevent a race with changing the rate control algorithm */
631 if (!netif_running(dev)) 645 if (!netif_running(dev))
@@ -641,16 +655,11 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
641 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 655 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
642 656
643 if (ieee80211_vif_is_mesh(&sdata->vif)) 657 if (ieee80211_vif_is_mesh(&sdata->vif))
644 sta = mesh_plink_add(mac, DEFAULT_RATES, sdata); 658 sta = mesh_plink_alloc(sdata, mac, DEFAULT_RATES, GFP_KERNEL);
645 else 659 else
646 sta = sta_info_add(sdata, mac); 660 sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
647 661 if (!sta)
648 if (IS_ERR(sta)) 662 return -ENOMEM;
649 return PTR_ERR(sta);
650
651 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
652 sdata->vif.type == IEEE80211_IF_TYPE_AP)
653 ieee80211_send_layer2_update(sta);
654 663
655 sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; 664 sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
656 665
@@ -658,6 +667,21 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
658 667
659 rate_control_rate_init(sta, local); 668 rate_control_rate_init(sta, local);
660 669
670 rcu_read_lock();
671
672 err = sta_info_insert(sta);
673 if (err) {
674 sta_info_destroy(sta);
675 rcu_read_unlock();
676 return err;
677 }
678
679 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
680 sdata->vif.type == IEEE80211_IF_TYPE_AP)
681 ieee80211_send_layer2_update(sta);
682
683 rcu_read_unlock();
684
661 return 0; 685 return 0;
662} 686}
663 687