summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaul Triebitz <shaul.triebitz@intel.com>2022-06-14 17:27:03 +0300
committerJohannes Berg <johannes.berg@intel.com>2022-07-15 11:43:13 +0200
commit21476ad16d3ca3687a474556c67d4789ef85a5df (patch)
treefa5fae69d56ce2e697af8a7bf249f1865ebe4f01
parentb95eb7f0eee479478eb1a7c0a42a80167708c1df (diff)
downloadlinux-21476ad16d3ca3687a474556c67d4789ef85a5df.tar.bz2
wifi: mac80211: implement callbacks for <add/mod/del>_link_station
Implement callbacks for cfg80211 add_link_station, mod_link_station, and del_link_station API. Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/cfg.c108
-rw-r--r--net/mac80211/sta_info.c7
-rw-r--r--net/mac80211/sta_info.h1
3 files changed, 116 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3eacf72279c2..85032dcaa595 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 d738534a709e..a4fa0ce7bd92 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 a1724e366a35..ea0eeee808a5 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);