wifi: mac80211: sta_info: fix link_sta insertion
When inserting a link STA, make sure it doesn't exist first and add lockdep assertions that we cannot modify the hash table without holding the sta_mtx, so this check is really correct. Also return without hashing if the driver failed, and warn if the hashing fails, which shouldn't happen due to the check described above. Fixes:cb71f1d136
("wifi: mac80211: add sta link addition/removal") Fixes:ba6ddab94f
("wifi: mac80211: maintain link-sta hash table") Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
b18d87f5d1
commit
177577dbd2
@ -99,6 +99,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
|
|||||||
static int link_sta_info_hash_add(struct ieee80211_local *local,
|
static int link_sta_info_hash_add(struct ieee80211_local *local,
|
||||||
struct link_sta_info *link_sta)
|
struct link_sta_info *link_sta)
|
||||||
{
|
{
|
||||||
|
lockdep_assert_held(&local->sta_mtx);
|
||||||
return rhltable_insert(&local->link_sta_hash,
|
return rhltable_insert(&local->link_sta_hash,
|
||||||
&link_sta->link_hash_node,
|
&link_sta->link_hash_node,
|
||||||
link_sta_rht_params);
|
link_sta_rht_params);
|
||||||
@ -107,6 +108,7 @@ static int link_sta_info_hash_add(struct ieee80211_local *local,
|
|||||||
static int link_sta_info_hash_del(struct ieee80211_local *local,
|
static int link_sta_info_hash_del(struct ieee80211_local *local,
|
||||||
struct link_sta_info *link_sta)
|
struct link_sta_info *link_sta)
|
||||||
{
|
{
|
||||||
|
lockdep_assert_held(&local->sta_mtx);
|
||||||
return rhltable_remove(&local->link_sta_hash,
|
return rhltable_remove(&local->link_sta_hash,
|
||||||
&link_sta->link_hash_node,
|
&link_sta->link_hash_node,
|
||||||
link_sta_rht_params);
|
link_sta_rht_params);
|
||||||
@ -2765,6 +2767,14 @@ int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
|
|||||||
if (WARN_ON(old_links == new_links || !link_sta))
|
if (WARN_ON(old_links == new_links || !link_sta))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
if (link_sta_info_hash_lookup(sdata->local, link_sta->addr)) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
return -EALREADY;
|
||||||
|
}
|
||||||
|
/* we only modify under the mutex so this is fine */
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
sta->sta.valid_links = new_links;
|
sta->sta.valid_links = new_links;
|
||||||
|
|
||||||
if (!test_sta_flag(sta, WLAN_STA_INSERTED)) {
|
if (!test_sta_flag(sta, WLAN_STA_INSERTED)) {
|
||||||
@ -2777,12 +2787,13 @@ int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
sta->sta.valid_links = old_links;
|
sta->sta.valid_links = old_links;
|
||||||
sta_remove_link(sta, link_id, false);
|
sta_remove_link(sta, link_id, false);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash:
|
hash:
|
||||||
link_sta_info_hash_add(sdata->local, link_sta);
|
ret = link_sta_info_hash_add(sdata->local, link_sta);
|
||||||
|
WARN_ON(ret);
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
|
void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user