wifi: mac80211: fix link sta hash table handling

There are two issues here: we unhash the link stations only
directly before freeing the station they belong to, and we
also don't unhash all the links correctly in all cases. Fix
these issues.

Fixes: ba6ddab94f ("wifi: mac80211: maintain link-sta hash table")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2022-07-18 22:54:27 +02:00
parent 9aebce6c97
commit 0ad49045f2

View file

@ -358,7 +358,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
if (!(sta->sta.valid_links & BIT(i))) if (!(sta->sta.valid_links & BIT(i)))
continue; continue;
sta_remove_link(sta, i, true); sta_remove_link(sta, i, false);
} }
/* /*
@ -846,6 +846,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
return 0; return 0;
out_remove: out_remove:
if (sta->sta.valid_links)
link_sta_info_hash_del(local, &sta->deflink);
sta_info_hash_del(local, sta); sta_info_hash_del(local, sta);
list_del_rcu(&sta->list); list_del_rcu(&sta->list);
out_drop_sta: out_drop_sta:
@ -1140,7 +1142,7 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
{ {
struct ieee80211_local *local; struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
int ret; int ret, i;
might_sleep(); might_sleep();
@ -1168,6 +1170,18 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
*/ */
drv_sync_rx_queues(local, sta); drv_sync_rx_queues(local, sta);
for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
struct link_sta_info *link_sta;
if (!(sta->sta.valid_links & BIT(i)))
continue;
link_sta = rcu_dereference_protected(sta->link[i],
lockdep_is_held(&local->sta_mtx));
link_sta_info_hash_del(local, link_sta);
}
ret = sta_info_hash_del(local, sta); ret = sta_info_hash_del(local, sta);
if (WARN_ON(ret)) if (WARN_ON(ret))
return ret; return ret;