Commit 0ad49045 authored by Johannes Berg's avatar Johannes Berg
Browse files

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: ba6ddab9 ("wifi: mac80211: maintain link-sta hash table")
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9aebce6c
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -358,7 +358,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
		if (!(sta->sta.valid_links & BIT(i)))
			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;
 out_remove:
	if (sta->sta.valid_links)
		link_sta_info_hash_del(local, &sta->deflink);
	sta_info_hash_del(local, sta);
	list_del_rcu(&sta->list);
 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_sub_if_data *sdata;
	int ret;
	int ret, i;

	might_sleep();

@@ -1168,6 +1170,18 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *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);
	if (WARN_ON(ret))
		return ret;