Commit 523d2f6982136d332c9b7dd00e9e16da1091f060
Committed by
John W. Linville
1 parent
8cdb045632
Exists in
master
and in
7 other branches
mac80211: fix todo lock
The key todo lock can be taken from different locks that require it to be _bh to avoid lock inversion due to (soft)irqs. This should fix the two problems reported by Bob and Gabor: http://mid.gmane.org/20090619113049.GB18956@hash.localnet http://mid.gmane.org/4A3FA376.8020307@openwrt.org Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Bob Copeland <me@bobcopeland.com> Cc: Gabor Juhos <juhosg@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 1 changed file with 15 additions and 13 deletions Side-by-side Diff
net/mac80211/key.c
... | ... | @@ -67,6 +67,8 @@ |
67 | 67 | * |
68 | 68 | * @key: key to add to do item for |
69 | 69 | * @flag: todo flag(s) |
70 | + * | |
71 | + * Must be called with IRQs or softirqs disabled. | |
70 | 72 | */ |
71 | 73 | static void add_todo(struct ieee80211_key *key, u32 flag) |
72 | 74 | { |
73 | 75 | |
... | ... | @@ -140,9 +142,9 @@ |
140 | 142 | ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); |
141 | 143 | |
142 | 144 | if (!ret) { |
143 | - spin_lock(&todo_lock); | |
145 | + spin_lock_bh(&todo_lock); | |
144 | 146 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
145 | - spin_unlock(&todo_lock); | |
147 | + spin_unlock_bh(&todo_lock); | |
146 | 148 | } |
147 | 149 | |
148 | 150 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) |
149 | 151 | |
150 | 152 | |
... | ... | @@ -164,12 +166,12 @@ |
164 | 166 | if (!key || !key->local->ops->set_key) |
165 | 167 | return; |
166 | 168 | |
167 | - spin_lock(&todo_lock); | |
169 | + spin_lock_bh(&todo_lock); | |
168 | 170 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
169 | - spin_unlock(&todo_lock); | |
171 | + spin_unlock_bh(&todo_lock); | |
170 | 172 | return; |
171 | 173 | } |
172 | - spin_unlock(&todo_lock); | |
174 | + spin_unlock_bh(&todo_lock); | |
173 | 175 | |
174 | 176 | sta = get_sta_for_key(key); |
175 | 177 | sdata = key->sdata; |
176 | 178 | |
... | ... | @@ -188,9 +190,9 @@ |
188 | 190 | wiphy_name(key->local->hw.wiphy), |
189 | 191 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
190 | 192 | |
191 | - spin_lock(&todo_lock); | |
193 | + spin_lock_bh(&todo_lock); | |
192 | 194 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
193 | - spin_unlock(&todo_lock); | |
195 | + spin_unlock_bh(&todo_lock); | |
194 | 196 | } |
195 | 197 | |
196 | 198 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
197 | 199 | |
... | ... | @@ -437,14 +439,14 @@ |
437 | 439 | |
438 | 440 | __ieee80211_key_replace(sdata, sta, old_key, key); |
439 | 441 | |
440 | - spin_unlock_irqrestore(&sdata->local->key_lock, flags); | |
441 | - | |
442 | 442 | /* free old key later */ |
443 | 443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); |
444 | 444 | |
445 | 445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); |
446 | 446 | if (netif_running(sdata->dev)) |
447 | 447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); |
448 | + | |
449 | + spin_unlock_irqrestore(&sdata->local->key_lock, flags); | |
448 | 450 | } |
449 | 451 | |
450 | 452 | static void __ieee80211_key_free(struct ieee80211_key *key) |
... | ... | @@ -547,7 +549,7 @@ |
547 | 549 | */ |
548 | 550 | synchronize_rcu(); |
549 | 551 | |
550 | - spin_lock(&todo_lock); | |
552 | + spin_lock_bh(&todo_lock); | |
551 | 553 | while (!list_empty(&todo_list)) { |
552 | 554 | key = list_first_entry(&todo_list, struct ieee80211_key, todo); |
553 | 555 | list_del_init(&key->todo); |
... | ... | @@ -558,7 +560,7 @@ |
558 | 560 | KEY_FLAG_TODO_HWACCEL_REMOVE | |
559 | 561 | KEY_FLAG_TODO_DELETE); |
560 | 562 | key->flags &= ~todoflags; |
561 | - spin_unlock(&todo_lock); | |
563 | + spin_unlock_bh(&todo_lock); | |
562 | 564 | |
563 | 565 | work_done = false; |
564 | 566 | |
565 | 567 | |
... | ... | @@ -591,9 +593,9 @@ |
591 | 593 | |
592 | 594 | WARN_ON(!work_done); |
593 | 595 | |
594 | - spin_lock(&todo_lock); | |
596 | + spin_lock_bh(&todo_lock); | |
595 | 597 | } |
596 | - spin_unlock(&todo_lock); | |
598 | + spin_unlock_bh(&todo_lock); | |
597 | 599 | } |
598 | 600 | |
599 | 601 | void ieee80211_key_todo(void) |