aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-04-08 11:56:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:45 -0400
commit3b96766f0e643f52ae19e134664df6730c737e87 (patch)
treeb1707d94a14c9777f09b1aab33970e7741190d4c /net/mac80211/sta_info.c
parent7d1559f1737d5ca27b267b0392015f42b3bbe2fa (diff)
mac80211: fix key vs. sta locking problems
Up to now, key manipulation is supposed to run under RTNL to avoid concurrent manipulations and also allow the set_key() hardware callback to sleep. This is not feasible because STA structs are rcu-protected and thus a lot of operations there cannot take the RTNL. Also, key references are rcu-protected so we cannot do things atomically. This patch changes key locking completely: * key operations are now atomic * hardware crypto offload is enabled and disabled from a workqueue, due to that key freeing is also delayed * debugfs code is also run from a workqueue * keys reference STAs (and vice versa!) so during STA unlink the STAs key reference is removed but not the keys STA reference, to avoid races key todo work is run before STA destruction. * fewer STA operations now need the RTNL which was required due to key operations This fixes the locking problems lockdep pointed out and also makes things more light-weight because the rtnl isn't required as much. Note that the key todo lock/key mutex are global locks, this is not required, of course, they could be per-hardware instead. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cedd73a0c875..5540cbf7c445 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -51,17 +51,15 @@
51 * 51 *
52 * In order to remove a STA info structure, the caller needs to first 52 * In order to remove a STA info structure, the caller needs to first
53 * unlink it (sta_info_unlink()) from the list and hash tables and 53 * unlink it (sta_info_unlink()) from the list and hash tables and
54 * then destroy it while holding the RTNL; sta_info_destroy() will wait 54 * then destroy it; sta_info_destroy() will wait for an RCU grace period
55 * for an RCU grace period to elapse before actually freeing it. Due to 55 * to elapse before actually freeing it. Due to the pinning and the
56 * the pinning and the possibility of multiple callers trying to remove 56 * possibility of multiple callers trying to remove the same STA info at
57 * the same STA info at the same time, sta_info_unlink() can clear the 57 * the same time, sta_info_unlink() can clear the STA info pointer it is
58 * STA info pointer it is passed to indicate that the STA info is owned 58 * passed to indicate that the STA info is owned by somebody else now.
59 * by somebody else now.
60 * 59 *
61 * If sta_info_unlink() did not clear the pointer then the caller owns 60 * If sta_info_unlink() did not clear the pointer then the caller owns
62 * the STA info structure now and is responsible of destroying it with 61 * the STA info structure now and is responsible of destroying it with
63 * a call to sta_info_destroy(), not before RCU synchronisation, of 62 * a call to sta_info_destroy().
64 * course. Note that sta_info_destroy() must be protected by the RTNL.
65 * 63 *
66 * In all other cases, there is no concept of ownership on a STA entry, 64 * In all other cases, there is no concept of ownership on a STA entry,
67 * each structure is owned by the global hash table/list until it is 65 * each structure is owned by the global hash table/list until it is
@@ -164,7 +162,6 @@ void sta_info_destroy(struct sta_info *sta)
164 struct sk_buff *skb; 162 struct sk_buff *skb;
165 int i; 163 int i;
166 164
167 ASSERT_RTNL();
168 might_sleep(); 165 might_sleep();
169 166
170 if (!sta) 167 if (!sta)
@@ -180,22 +177,16 @@ void sta_info_destroy(struct sta_info *sta)
180 mesh_plink_deactivate(sta); 177 mesh_plink_deactivate(sta);
181#endif 178#endif
182 179
183 if (sta->key) { 180 /*
184 /* 181 * We have only unlinked the key, and actually destroying it
185 * NOTE: This will call synchronize_rcu() internally to 182 * may mean it is removed from hardware which requires that
186 * make sure no key references can be in use. We rely on 183 * the key->sta pointer is still valid, so flush the key todo
187 * that when we take this branch to make sure nobody can 184 * list here.
188 * reference this STA struct any longer! 185 *
189 */ 186 * ieee80211_key_todo() will synchronize_rcu() so after this
190 ieee80211_key_free(sta->key); 187 * nothing can reference this sta struct any more.
191 WARN_ON(sta->key); 188 */
192 } else { 189 ieee80211_key_todo();
193 /*
194 * Make sure that nobody can reference this STA struct
195 * any longer.
196 */
197 synchronize_rcu();
198 }
199 190
200#ifdef CONFIG_MAC80211_MESH 191#ifdef CONFIG_MAC80211_MESH
201 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) 192 if (ieee80211_vif_is_mesh(&sta->sdata->vif))
@@ -439,6 +430,11 @@ void __sta_info_unlink(struct sta_info **sta)
439 return; 430 return;
440 } 431 }
441 432
433 if ((*sta)->key) {
434 ieee80211_key_free((*sta)->key);
435 WARN_ON((*sta)->key);
436 }
437
442 list_del(&(*sta)->list); 438 list_del(&(*sta)->list);
443 439
444 if ((*sta)->flags & WLAN_STA_PS) { 440 if ((*sta)->flags & WLAN_STA_PS) {
@@ -652,7 +648,7 @@ static void sta_info_debugfs_add_work(struct work_struct *work)
652} 648}
653#endif 649#endif
654 650
655void __ieee80211_run_pending_flush(struct ieee80211_local *local) 651static void __ieee80211_run_pending_flush(struct ieee80211_local *local)
656{ 652{
657 struct sta_info *sta; 653 struct sta_info *sta;
658 unsigned long flags; 654 unsigned long flags;