From f689bf1cf18b473e82deab670a04064c2ce0db32 Mon Sep 17 00:00:00 2001 From: Aaradhana Sahu Date: Fri, 16 Dec 2022 15:58:50 +0530 Subject: [PATCH] mac80211: add support for set link specific tx power Currently, we set tx power form user space according to phy and each phy has particular band and tx power,but in multi-link operation each phy has more than one link and each link is working on different band, tx power. So, add support set tx power according to link id. Signed-off-by: Aaradhana Sahu --- net/mac80211/cfg.c | 24 ++++++++++++++--------- net/mac80211/chan.c | 4 ++-- net/mac80211/ieee80211_i.h | 5 +++-- net/mac80211/iface.c | 39 +++++++++++++++++++++++++------------- net/mac80211/link.c | 4 ++++ net/mac80211/mlme.c | 2 +- 6 files changed, 51 insertions(+), 27 deletions(-) --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3071,17 +3071,23 @@ static int ieee80211_set_wiphy_params(st static int ieee80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, - enum nl80211_tx_power_setting type, int mbm) + enum nl80211_tx_power_setting type, + int mbm, unsigned int link_id) { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; enum nl80211_tx_power_setting txp_type = type; bool update_txp_type = false; bool has_monitor = false; + struct ieee80211_link_data *link_data; if (wdev) { sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); + link_data = sdata_dereference(sdata->link[link_id], sdata); + if (!link_data) + return -ENOLINK; + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); @@ -3091,7 +3097,7 @@ static int ieee80211_set_tx_power(struct switch (type) { case NL80211_TX_POWER_AUTOMATIC: - sdata->deflink.user_power_level = + link_data->user_power_level = IEEE80211_UNSET_POWER_LEVEL; txp_type = NL80211_TX_POWER_LIMITED; break; @@ -3099,16 +3105,16 @@ static int ieee80211_set_tx_power(struct case NL80211_TX_POWER_FIXED: if (mbm < 0 || (mbm % 100)) return -EOPNOTSUPP; - sdata->deflink.user_power_level = MBM_TO_DBM(mbm); + link_data->user_power_level = MBM_TO_DBM(mbm); break; } - if (txp_type != sdata->vif.bss_conf.txpower_type) { + if (txp_type != link_data->conf->txpower_type) { update_txp_type = true; - sdata->vif.bss_conf.txpower_type = txp_type; + link_data->conf->txpower_type = txp_type; } - ieee80211_recalc_txpower(sdata, update_txp_type); + ieee80211_recalc_txpower(sdata, update_txp_type, link_id); return 0; } @@ -3126,6 +3132,7 @@ static int ieee80211_set_tx_power(struct break; } + /*TODO: monitor mode for MLO */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { @@ -3140,7 +3147,7 @@ static int ieee80211_set_tx_power(struct list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) continue; - ieee80211_recalc_txpower(sdata, update_txp_type); + ieee80211_recalc_txpower(sdata, update_txp_type, link_id); } mutex_unlock(&local->iflist_mtx); @@ -3153,7 +3160,7 @@ static int ieee80211_set_tx_power(struct update_txp_type = true; sdata->vif.bss_conf.txpower_type = txp_type; - ieee80211_recalc_txpower(sdata, update_txp_type); + ieee80211_recalc_txpower(sdata, update_txp_type, 0); } } --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -899,7 +899,7 @@ out: } if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) { - ieee80211_recalc_txpower(sdata, false); + ieee80211_recalc_txpower(sdata, false, link->link_id); ieee80211_recalc_chanctx_min_def(local, new_ctx); } @@ -1686,7 +1686,7 @@ static int ieee80211_vif_use_reserved_sw link, changed); - ieee80211_recalc_txpower(sdata, false); + ieee80211_recalc_txpower(sdata, false, link->link_id); } ieee80211_recalc_chanctx_chantype(local, ctx); --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1983,9 +1983,10 @@ void ieee80211_sdata_stop(struct ieee802 int ieee80211_add_virtual_monitor(struct ieee80211_local *local); void ieee80211_del_virtual_monitor(struct ieee80211_local *local); -bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); +bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, + unsigned int link_id); void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, - bool update_bss); + bool update_bss, unsigned int link_id); void ieee80211_recalc_offload(struct ieee80211_local *local); static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -57,13 +57,20 @@ MODULE_PARM_DESC(ppe_vp_accel, "module p static void ieee80211_iface_work(struct work_struct *work); -bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) +bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, + unsigned int link_id) { struct ieee80211_chanctx_conf *chanctx_conf; int power; + struct ieee80211_link_data *link_data; + + link_data = sdata_dereference(sdata->link[link_id], sdata); + if (!link_data) + return false; rcu_read_lock(); - chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); + + chanctx_conf = rcu_dereference(link_data->conf->chanctx_conf); if (!chanctx_conf) { rcu_read_unlock(); return false; @@ -72,14 +79,14 @@ bool __ieee80211_recalc_txpower(struct i power = ieee80211_chandef_max_power(&chanctx_conf->def); rcu_read_unlock(); - if (sdata->deflink.user_power_level != IEEE80211_UNSET_POWER_LEVEL) - power = min(power, sdata->deflink.user_power_level); + if (link_data->user_power_level != IEEE80211_UNSET_POWER_LEVEL) + power = min(power, link_data->user_power_level); - if (sdata->deflink.ap_power_level != IEEE80211_UNSET_POWER_LEVEL) - power = min(power, sdata->deflink.ap_power_level); + if (link_data->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) + power = min(power, link_data->ap_power_level); - if (power != sdata->vif.bss_conf.txpower) { - sdata->vif.bss_conf.txpower = power; + if (power != link_data->conf->txpower) { + link_data->conf->txpower = power; ieee80211_hw_config(sdata->local, 0); return true; } @@ -88,12 +95,19 @@ bool __ieee80211_recalc_txpower(struct i } void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, - bool update_bss) + bool update_bss, unsigned int link_id) { - if (__ieee80211_recalc_txpower(sdata) || - (update_bss && ieee80211_sdata_running(sdata))) - ieee80211_link_info_change_notify(sdata, &sdata->deflink, + if (__ieee80211_recalc_txpower(sdata, link_id) || + (update_bss && ieee80211_sdata_running(sdata))) { + struct ieee80211_link_data *link_data; + + link_data = sdata_dereference(sdata->link[link_id], sdata); + if (!link_data) + return; + + ieee80211_link_info_change_notify(sdata, link_data, BSS_CHANGED_TXPOWER); + } } static u32 __ieee80211_idle_off(struct ieee80211_local *local) @@ -2316,7 +2330,6 @@ int ieee80211_if_add(struct ieee80211_lo sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL; sdata->deflink.user_power_level = local->user_power_level; - /* setup type-dependent data */ ieee80211_setup_sdata(sdata, type); --- a/net/mac80211/link.c +++ b/net/mac80211/link.c @@ -21,6 +21,7 @@ void ieee80211_link_init(struct ieee8021 struct ieee80211_link_data *link, struct ieee80211_bss_conf *link_conf) { + struct ieee80211_local *local = sdata->local; bool deflink = link_id < 0; if (link_id < 0) @@ -43,6 +44,9 @@ void ieee80211_link_init(struct ieee8021 INIT_DELAYED_WORK(&link->dfs_cac_timer_work, ieee80211_dfs_cac_timer_work); + link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; + link->user_power_level = local->user_power_level; + if (!deflink) { switch (sdata->vif.type) { case NL80211_IFTYPE_AP: --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2095,7 +2095,7 @@ static u32 ieee80211_handle_pwr_constr(s } link->ap_power_level = new_ap_level; - if (__ieee80211_recalc_txpower(sdata)) + if (__ieee80211_recalc_txpower(sdata, 0)) return BSS_CHANGED_TXPOWER; return 0; }