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: ba6ddab94f
("wifi: mac80211: maintain link-sta hash table")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
d46ffecf82
commit
f36fe0a2df
7 changed files with 56 additions and 20 deletions
|
@ -1850,8 +1850,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
||||||
!sdata->u.mgd.associated)
|
!sdata->u.mgd.associated)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sta = sta_info_alloc(sdata, mac, params->link_sta_params.link_id,
|
if (params->link_sta_params.link_id >= 0)
|
||||||
GFP_KERNEL);
|
sta = sta_info_alloc_with_link(sdata, mac,
|
||||||
|
params->link_sta_params.link_id,
|
||||||
|
params->link_sta_params.link_mac,
|
||||||
|
GFP_KERNEL);
|
||||||
|
else
|
||||||
|
sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
|
||||||
|
|
||||||
if (!sta)
|
if (!sta)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -625,7 +625,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
|
||||||
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
|
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
sta = sta_info_alloc(sdata, addr, -1, GFP_KERNEL);
|
sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1226,7 +1226,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
|
||||||
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
|
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
sta = sta_info_alloc(sdata, addr, -1, GFP_ATOMIC);
|
sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
|
||||||
if (!sta)
|
if (!sta)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -511,7 +511,7 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
|
||||||
if (aid < 0)
|
if (aid < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sta = sta_info_alloc(sdata, hw_addr, -1, GFP_KERNEL);
|
sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
|
||||||
if (!sta)
|
if (!sta)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
@ -5909,7 +5909,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!have_sta) {
|
if (!have_sta) {
|
||||||
new_sta = sta_info_alloc(sdata, cbss->bssid, -1, GFP_KERNEL);
|
new_sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
|
||||||
if (!new_sta)
|
if (!new_sta)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
|
||||||
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
|
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
sta = sta_info_alloc(sdata, addr, -1, GFP_ATOMIC);
|
sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
|
||||||
if (!sta)
|
if (!sta)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,14 @@ static int sta_info_hash_del(struct ieee80211_local *local,
|
||||||
sta_rht_params);
|
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,
|
static int link_sta_info_hash_del(struct ieee80211_local *local,
|
||||||
struct link_sta_info *link_sta)
|
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);
|
rcu_assign_pointer(sta->sta.link[link_id], link_sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
static struct sta_info *
|
||||||
const u8 *addr, int link_id, gfp_t gfp)
|
__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_local *local = sdata->local;
|
||||||
struct ieee80211_hw *hw = &local->hw;
|
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->addr, addr, ETH_ALEN);
|
||||||
memcpy(sta->sta.addr, addr, ETH_ALEN);
|
memcpy(sta->sta.addr, addr, ETH_ALEN);
|
||||||
memcpy(sta->deflink.addr, addr, ETH_ALEN);
|
memcpy(sta->deflink.addr, link_addr, ETH_ALEN);
|
||||||
memcpy(sta->sta.deflink.addr, addr, ETH_ALEN);
|
memcpy(sta->sta.deflink.addr, link_addr, ETH_ALEN);
|
||||||
sta->sta.max_rx_aggregation_subframes =
|
sta->sta.max_rx_aggregation_subframes =
|
||||||
local->hw.max_rx_aggregation_subframes;
|
local->hw.max_rx_aggregation_subframes;
|
||||||
|
|
||||||
|
@ -641,6 +651,21 @@ free:
|
||||||
return NULL;
|
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)
|
static int sta_info_insert_check(struct sta_info *sta)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
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)
|
if (err)
|
||||||
goto out_drop_sta;
|
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);
|
list_add_tail_rcu(&sta->list, &local->sta_list);
|
||||||
|
|
||||||
/* update channel context before notifying the driver about state
|
/* 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;
|
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)
|
void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id)
|
||||||
{
|
{
|
||||||
lockdep_assert_held(&sta->sdata->local->sta_mtx);
|
lockdep_assert_held(&sta->sdata->local->sta_mtx);
|
||||||
|
|
|
@ -840,7 +840,12 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
|
||||||
* until sta_info_insert().
|
* until sta_info_insert().
|
||||||
*/
|
*/
|
||||||
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
||||||
const u8 *addr, int link_id, gfp_t gfp);
|
const u8 *addr, gfp_t 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);
|
||||||
|
|
||||||
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
|
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue