aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-02-03 07:59:58 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-02-08 16:50:53 -0500
commit34e895075e21be3e21e71d6317440d1ee7969ad0 (patch)
tree217fe70e32e54ef0134f477510472f3992655d79 /net/mac80211/util.c
parent070bb5477fb4029131aad4941d7aaf0093db0c38 (diff)
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/util.c')
-rw-r--r--net/mac80211/util.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ca170b417da6..3af439a85b33 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1082,7 +1082,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1082 struct ieee80211_hw *hw = &local->hw; 1082 struct ieee80211_hw *hw = &local->hw;
1083 struct ieee80211_sub_if_data *sdata; 1083 struct ieee80211_sub_if_data *sdata;
1084 struct sta_info *sta; 1084 struct sta_info *sta;
1085 unsigned long flags;
1086 int res; 1085 int res;
1087 1086
1088 if (local->suspended) 1087 if (local->suspended)
@@ -1116,20 +1115,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1116 } 1115 }
1117 1116
1118 /* add STAs back */ 1117 /* add STAs back */
1119 if (local->ops->sta_notify) { 1118 mutex_lock(&local->sta_mtx);
1120 spin_lock_irqsave(&local->sta_lock, flags); 1119 list_for_each_entry(sta, &local->sta_list, list) {
1121 list_for_each_entry(sta, &local->sta_list, list) { 1120 if (sta->uploaded) {
1122 sdata = sta->sdata; 1121 sdata = sta->sdata;
1123 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1122 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1124 sdata = container_of(sdata->bss, 1123 sdata = container_of(sdata->bss,
1125 struct ieee80211_sub_if_data, 1124 struct ieee80211_sub_if_data,
1126 u.ap); 1125 u.ap);
1127 1126
1128 drv_sta_notify(local, sdata, STA_NOTIFY_ADD, 1127 WARN_ON(drv_sta_add(local, sdata, &sta->sta));
1129 &sta->sta);
1130 } 1128 }
1131 spin_unlock_irqrestore(&local->sta_lock, flags);
1132 } 1129 }
1130 mutex_unlock(&local->sta_mtx);
1133 1131
1134 /* Clear Suspend state so that ADDBA requests can be processed */ 1132 /* Clear Suspend state so that ADDBA requests can be processed */
1135 1133
@@ -1219,10 +1217,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1219 1217
1220 add_timer(&local->sta_cleanup); 1218 add_timer(&local->sta_cleanup);
1221 1219
1222 spin_lock_irqsave(&local->sta_lock, flags); 1220 mutex_lock(&local->sta_mtx);
1223 list_for_each_entry(sta, &local->sta_list, list) 1221 list_for_each_entry(sta, &local->sta_list, list)
1224 mesh_plink_restart(sta); 1222 mesh_plink_restart(sta);
1225 spin_unlock_irqrestore(&local->sta_lock, flags); 1223 mutex_unlock(&local->sta_mtx);
1226#else 1224#else
1227 WARN_ON(1); 1225 WARN_ON(1);
1228#endif 1226#endif