From: Shaul Triebitz Date: Tue, 14 Jun 2022 14:27:03 +0000 (+0300) Subject: wifi: mac80211: implement callbacks for _link_station X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=21476ad16d3ca3687a474556c67d4789ef85a5df;p=linux.git wifi: mac80211: implement callbacks for _link_station Implement callbacks for cfg80211 add_link_station, mod_link_station, and del_link_station API. Signed-off-by: Shaul Triebitz Signed-off-by: Johannes Berg --- diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3eacf72279c24..85032dcaa595d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -4588,6 +4588,111 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy, ieee80211_vif_set_links(sdata, wdev->valid_links); } +static int sta_add_link_station(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct link_station_parameters *params) +{ + struct sta_info *sta; + int ret; + + sta = sta_info_get_bss(sdata, params->mld_mac); + if (!sta) + return -ENOENT; + + if (sta->sta.valid_links & BIT(params->link_id)) + return -EALREADY; + + ret = ieee80211_sta_allocate_link(sta, params->link_id); + if (ret) + return ret; + + ret = sta_link_apply_parameters(local, sta, params); + if (ret) { + ieee80211_sta_free_link(sta, params->link_id); + return ret; + } + + /* ieee80211_sta_activate_link frees the link upon failure */ + return ieee80211_sta_activate_link(sta, params->link_id); +} + +static int +ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev, + struct link_station_parameters *params) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = wiphy_priv(wiphy); + int ret; + + mutex_lock(&sdata->local->sta_mtx); + ret = sta_add_link_station(local, sdata, params); + mutex_unlock(&sdata->local->sta_mtx); + + return ret; +} + +static int sta_mod_link_station(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct link_station_parameters *params) +{ + struct sta_info *sta; + + sta = sta_info_get_bss(sdata, params->mld_mac); + if (!sta) + return -ENOENT; + + if (!(sta->sta.valid_links & BIT(params->link_id))) + return -EINVAL; + + return sta_link_apply_parameters(local, sta, params); +} + +static int +ieee80211_mod_link_station(struct wiphy *wiphy, struct net_device *dev, + struct link_station_parameters *params) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = wiphy_priv(wiphy); + int ret; + + mutex_lock(&sdata->local->sta_mtx); + ret = sta_mod_link_station(local, sdata, params); + mutex_unlock(&sdata->local->sta_mtx); + + return ret; +} + +static int sta_del_link_station(struct ieee80211_sub_if_data *sdata, + struct link_station_del_parameters *params) +{ + struct sta_info *sta; + + sta = sta_info_get_bss(sdata, params->mld_mac); + if (!sta) + return -ENOENT; + + if (!(sta->sta.valid_links & BIT(params->link_id))) + return -EINVAL; + + ieee80211_sta_remove_link(sta, params->link_id); + + return 0; +} + +static int +ieee80211_del_link_station(struct wiphy *wiphy, struct net_device *dev, + struct link_station_del_parameters *params) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + int ret; + + mutex_lock(&sdata->local->sta_mtx); + ret = sta_del_link_station(sdata, params); + mutex_unlock(&sdata->local->sta_mtx); + + return ret; +} + const struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -4695,4 +4800,7 @@ const struct cfg80211_ops mac80211_config_ops = { .set_radar_background = ieee80211_set_radar_background, .add_intf_link = ieee80211_add_intf_link, .del_intf_link = ieee80211_del_intf_link, + .add_link_station = ieee80211_add_link_station, + .mod_link_station = ieee80211_mod_link_station, + .del_link_station = ieee80211_del_link_station, }; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d738534a709ed..a4fa0ce7bd922 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2702,6 +2702,13 @@ static int link_sta_info_hash_add(struct ieee80211_local *local, 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); + + sta_remove_link(sta, link_id, false); +} + int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id) { struct ieee80211_sub_if_data *sdata = sta->sdata; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index a1724e366a354..ea0eeee808a5c 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -900,6 +900,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time); int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id); +void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id); int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id); void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id);