summaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_sta.c
diff options
context:
space:
mode:
authorMichael Wu <flamingice@sourmilk.net>2007-07-27 15:43:23 +0200
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 16:47:37 -0700
commitbe8755e1804d6f60e6a96a46ac6bc46ce6dfca53 (patch)
treea3038a924114f49aa2372ab7c9417d4e072c4b20 /net/mac80211/ieee80211_sta.c
parentc2d1560ad8c2f6e0dd0d34102d022f3709325c26 (diff)
[MAC80211]: improve locking of sta_info related structures
The sta_info code has some awkward locking which prevents some driver callbacks from being allowed to sleep. This patch makes the locking more focused so code that calls driver callbacks are allowed to sleep. It also converts sta_lock to a rwlock. Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: Jiri Benc <jbenc@suse.cz> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r--net/mac80211/ieee80211_sta.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 0d99b685df5..9aee1abae12 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -773,7 +773,7 @@ static void ieee80211_associated(struct net_device *dev,
"range\n",
dev->name, MAC_ARG(ifsta->bssid));
disassoc = 1;
- sta_info_free(sta, 0);
+ sta_info_free(sta);
ifsta->probereq_poll = 0;
} else {
ieee80211_send_probe_req(dev, ifsta->bssid,
@@ -1890,7 +1890,7 @@ static int ieee80211_sta_active_ibss(struct net_device *dev)
int active = 0;
struct sta_info *sta;
- spin_lock_bh(&local->sta_lock);
+ read_lock_bh(&local->sta_lock);
list_for_each_entry(sta, &local->sta_list, list) {
if (sta->dev == dev &&
time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
@@ -1899,7 +1899,7 @@ static int ieee80211_sta_active_ibss(struct net_device *dev)
break;
}
}
- spin_unlock_bh(&local->sta_lock);
+ read_unlock_bh(&local->sta_lock);
return active;
}
@@ -1909,16 +1909,24 @@ static void ieee80211_sta_expire(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta, *tmp;
+ LIST_HEAD(tmp_list);
- spin_lock_bh(&local->sta_lock);
+ write_lock_bh(&local->sta_lock);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx +
IEEE80211_IBSS_INACTIVITY_LIMIT)) {
printk(KERN_DEBUG "%s: expiring inactive STA " MAC_FMT
"\n", dev->name, MAC_ARG(sta->addr));
- sta_info_free(sta, 1);
+ __sta_info_get(sta);
+ sta_info_remove(sta);
+ list_add(&sta->list, &tmp_list);
}
- spin_unlock_bh(&local->sta_lock);
+ write_unlock_bh(&local->sta_lock);
+
+ list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
+ sta_info_free(sta);
+ sta_info_put(sta);
+ }
}