diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2010-02-03 13:59:58 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-02-08 16:50:53 -0500 |
commit | 34e895075e21be3e21e71d6317440d1ee7969ad0 (patch) | |
tree | 217fe70e32e54ef0134f477510472f3992655d79 /net/mac80211/cfg.c | |
parent | 070bb5477fb4029131aad4941d7aaf0093db0c38 (diff) | |
download | linux-34e895075e21be3e21e71d6317440d1ee7969ad0.tar.bz2 |
mac80211: allow station add/remove to sleep
Many drivers would like to sleep during station
addition and removal, and currently have a high
complexity there from not being able to.
This introduces two new callbacks sta_add() and
sta_remove() that drivers can implement instead
of using sta_notify() and that can sleep, and
the new sta_add() callback is also allowed to
fail.
The reason we didn't do this previously is that
the IBSS code wants to insert stations from the
RX path, which is a tasklet, so cannot sleep.
This patch will keep the station allocation in
that path, but moves adding the station to the
driver out of line. Since the addition can now
fail, we can have IBSS peer structs the driver
rejected -- in that case we still talk to the
station but never tell the driver about it in
the control.sta pointer. If there will ever be
a driver that has a low limit on the number of
stations and that cannot talk to any stations
that are not known to it, we need to do come up
with a new strategy of handling larger IBSSs,
maybe quicker expiry or rejecting peers.
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.c | 23 |
1 files changed, 4 insertions, 19 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index facf233843e0..a362523d8eb7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -747,9 +747,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || sdata->vif.type == NL80211_IFTYPE_AP; - rcu_read_lock(); - - err = sta_info_insert(sta); + err = sta_info_insert_rcu(sta); if (err) { rcu_read_unlock(); return err; @@ -768,26 +766,13 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; - struct sta_info *sta; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (mac) { - rcu_read_lock(); - - sta = sta_info_get_bss(sdata, mac); - if (!sta) { - rcu_read_unlock(); - return -ENOENT; - } - - sta_info_unlink(&sta); - rcu_read_unlock(); - - sta_info_destroy(sta); - } else - sta_info_flush(local, sdata); + if (mac) + return sta_info_destroy_addr_bss(sdata, mac); + sta_info_flush(local, sdata); return 0; } |