@@ -261,7 +261,7 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
bool defunikey, defmultikey, defmgmtkey;
if (new)
- list_add_tail(&new->list, &sdata->key_list);
+ list_add_tail_rcu(&new->list, &sdata->key_list);
if (sta && pairwise) {
rcu_assign_pointer(sta->ptk, new);
@@ -309,7 +309,7 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
}
if (old)
- list_del(&old->list);
+ list_del_rcu(&old->list);
}
struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
@@ -537,6 +537,10 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
mutex_unlock(&sdata->local->key_mtx);
}
+/*
+ * This function is supposed to be used for reading operations only.
+ * Iterations over the key list are performed with RCU_read lock only
+ */
void ieee80211_iter_keys(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
void (*iter)(struct ieee80211_hw *hw,
@@ -547,27 +551,24 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
void *iter_data)
{
struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_key *key, *tmp;
struct ieee80211_sub_if_data *sdata;
mutex_lock(&local->key_mtx);
+ rcu_read_lock();
if (vif) {
sdata = vif_to_sdata(vif);
- list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
+ list_for_each_entry(key, &sdata->key_list, list)
iter(hw, &sdata->vif,
key->sta ? &key->sta->sta : NULL,
&key->conf, iter_data);
} else {
- rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
- list_for_each_entry_safe(key, tmp,
- &sdata->key_list, list)
+ list_for_each_entry_rcu(key, &sdata->key_list, list)
iter(hw, &sdata->vif,
key->sta ? &key->sta->sta : NULL,
&key->conf, iter_data);
- rcu_read_unlock();
}
- mutex_unlock(&local->key_mtx);
+ rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_iter_keys);