diff options
Diffstat (limited to 'package/mac80211/patches/008-mac80211-fix-todo-lock.patch')
-rw-r--r-- | package/mac80211/patches/008-mac80211-fix-todo-lock.patch | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/package/mac80211/patches/008-mac80211-fix-todo-lock.patch b/package/mac80211/patches/008-mac80211-fix-todo-lock.patch new file mode 100644 index 0000000000..61ed2b30e9 --- /dev/null +++ b/package/mac80211/patches/008-mac80211-fix-todo-lock.patch @@ -0,0 +1,117 @@ +From: Johannes Berg <johannes@sipsolutions.net> +Subject: 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> +--- + net/mac80211/key.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -70,6 +70,8 @@ static DECLARE_WORK(todo_work, key_todo) + * + * @key: key to add to do item for + * @flag: todo flag(s) ++ * ++ * Must be called with IRQs or softirqs disabled. + */ + static void add_todo(struct ieee80211_key *key, u32 flag) + { +@@ -143,9 +145,9 @@ static void ieee80211_key_enable_hw_acce + ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); + + if (!ret) { +- spin_lock(&todo_lock); ++ spin_lock_bh(&todo_lock); + key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; +- spin_unlock(&todo_lock); ++ spin_unlock_bh(&todo_lock); + } + + if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) +@@ -167,12 +169,12 @@ static void ieee80211_key_disable_hw_acc + if (!key || !key->local->ops->set_key) + return; + +- spin_lock(&todo_lock); ++ spin_lock_bh(&todo_lock); + if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { +- spin_unlock(&todo_lock); ++ spin_unlock_bh(&todo_lock); + return; + } +- spin_unlock(&todo_lock); ++ spin_unlock_bh(&todo_lock); + + sta = get_sta_for_key(key); + sdata = key->sdata; +@@ -191,9 +193,9 @@ static void ieee80211_key_disable_hw_acc + wiphy_name(key->local->hw.wiphy), + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + +- spin_lock(&todo_lock); ++ spin_lock_bh(&todo_lock); + key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; +- spin_unlock(&todo_lock); ++ spin_unlock_bh(&todo_lock); + } + + static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, +@@ -440,14 +442,14 @@ void ieee80211_key_link(struct ieee80211 + + __ieee80211_key_replace(sdata, sta, old_key, key); + +- spin_unlock_irqrestore(&sdata->local->key_lock, flags); +- + /* free old key later */ + add_todo(old_key, KEY_FLAG_TODO_DELETE); + + add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); + if (netif_running(sdata->dev)) + add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); ++ ++ spin_unlock_irqrestore(&sdata->local->key_lock, flags); + } + + static void __ieee80211_key_free(struct ieee80211_key *key) +@@ -550,7 +552,7 @@ static void __ieee80211_key_todo(void) + */ + synchronize_rcu(); + +- spin_lock(&todo_lock); ++ spin_lock_bh(&todo_lock); + while (!list_empty(&todo_list)) { + key = list_first_entry(&todo_list, struct ieee80211_key, todo); + list_del_init(&key->todo); +@@ -561,7 +563,7 @@ static void __ieee80211_key_todo(void) + KEY_FLAG_TODO_HWACCEL_REMOVE | + KEY_FLAG_TODO_DELETE); + key->flags &= ~todoflags; +- spin_unlock(&todo_lock); ++ spin_unlock_bh(&todo_lock); + + work_done = false; + +@@ -594,9 +596,9 @@ static void __ieee80211_key_todo(void) + + WARN_ON(!work_done); + +- spin_lock(&todo_lock); ++ spin_lock_bh(&todo_lock); + } +- spin_unlock(&todo_lock); ++ spin_unlock_bh(&todo_lock); + } + + void ieee80211_key_todo(void) |