From f36fe0a2df03209f4d681fa954f20bfa4eefec45 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Jul 2022 23:40:47 +0200 Subject: wifi: mac80211: fix up link station creation/insertion When we create a station with a non-default link, then we should have a link address, and we definitely need to insert it into the link hash table on insertion. Split the API into with and without link creation and if it has a link, insert the link into the link hash table on sta_info_insert(). Fixes: ba6ddab94fc6 ("wifi: mac80211: maintain link-sta hash table") Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'net/mac80211/sta_info.c') diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index eed88630594f..75122eced104 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -96,6 +96,14 @@ static int sta_info_hash_del(struct ieee80211_local *local, sta_rht_params); } +static int link_sta_info_hash_add(struct ieee80211_local *local, + struct link_sta_info *link_sta) +{ + return rhltable_insert(&local->link_sta_hash, + &link_sta->link_hash_node, + link_sta_rht_params); +} + static int link_sta_info_hash_del(struct ieee80211_local *local, struct link_sta_info *link_sta) { @@ -466,8 +474,10 @@ static void sta_info_add_link(struct sta_info *sta, rcu_assign_pointer(sta->sta.link[link_id], link_sta); } -struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, - const u8 *addr, int link_id, gfp_t gfp) +static struct sta_info * +__sta_info_alloc(struct ieee80211_sub_if_data *sdata, + const u8 *addr, int link_id, const u8 *link_addr, + gfp_t gfp) { struct ieee80211_local *local = sdata->local; struct ieee80211_hw *hw = &local->hw; @@ -513,8 +523,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, memcpy(sta->addr, addr, ETH_ALEN); memcpy(sta->sta.addr, addr, ETH_ALEN); - memcpy(sta->deflink.addr, addr, ETH_ALEN); - memcpy(sta->sta.deflink.addr, addr, ETH_ALEN); + memcpy(sta->deflink.addr, link_addr, ETH_ALEN); + memcpy(sta->sta.deflink.addr, link_addr, ETH_ALEN); sta->sta.max_rx_aggregation_subframes = local->hw.max_rx_aggregation_subframes; @@ -641,6 +651,21 @@ free: return NULL; } +struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, + const u8 *addr, gfp_t gfp) +{ + return __sta_info_alloc(sdata, addr, -1, addr, gfp); +} + +struct sta_info *sta_info_alloc_with_link(struct ieee80211_sub_if_data *sdata, + const u8 *mld_addr, + unsigned int link_id, + const u8 *link_addr, + gfp_t gfp) +{ + return __sta_info_alloc(sdata, mld_addr, link_id, link_addr, gfp); +} + static int sta_info_insert_check(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -774,6 +799,14 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) if (err) goto out_drop_sta; + if (sta->sta.valid_links) { + err = link_sta_info_hash_add(local, &sta->deflink); + if (err) { + sta_info_hash_del(local, sta); + goto out_drop_sta; + } + } + list_add_tail_rcu(&sta->list, &local->sta_list); /* update channel context before notifying the driver about state @@ -2697,14 +2730,6 @@ int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id) return 0; } -static int link_sta_info_hash_add(struct ieee80211_local *local, - struct link_sta_info *link_sta) -{ - return rhltable_insert(&local->link_sta_hash, - &link_sta->link_hash_node, - link_sta_rht_params); -} - void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id) { lockdep_assert_held(&sta->sdata->local->sta_mtx); -- cgit v1.2.3