Enable/disable per packet Transmit Power Control (TPC) in lower drivers according to TX power settings configured by the user. In particular TPC is enabled if value passed in enum nl80211_tx_power_setting is NL80211_TX_POWER_AUTOMATIC (no limit from userspace) or NL80211_TX_POWER_LIMITED (allow using less than specified from userspace), whereas TPC is disabled if nl80211_tx_power_setting is set to NL80211_TX_POWER_FIXED (use value configured from userspace) Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@xxxxxxxxx> --- include/net/mac80211.h | 10 ++++++++++ net/mac80211/cfg.c | 6 +++++- net/mac80211/ieee80211_i.h | 1 + net/mac80211/iface.c | 8 +++++++- net/mac80211/main.c | 8 +++++++- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cff3a26..7dd2432 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -376,6 +376,8 @@ enum ieee80211_rssi_event { * @ssid_len: Length of SSID given in @ssid. * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode. * @txpower: TX power in dBm + * @tpc_enabled: enable/disable per packet Transmit Power Control (TPC) for the + * current vif * @p2p_noa_attr: P2P NoA attribute for P2P powersave */ struct ieee80211_bss_conf { @@ -411,6 +413,7 @@ struct ieee80211_bss_conf { size_t ssid_len; bool hidden_ssid; int txpower; + bool tpc_enabled; struct ieee80211_p2p_noa_attr p2p_noa_attr; }; @@ -1115,6 +1118,12 @@ enum ieee80211_smps_mode { * * @power_level: requested transmit power (in dBm), backward compatibility * value only that is set to the minimum of all interfaces + * @tpc_enabled: enable/disable per packet Transmit Power Control (TPC) in + * lower driver. TPC is enabled if value passed in + * nl80211_tx_power_setting is %NL80211_TX_POWER_AUTOMATIC (no limit from + * userspace) or %NL80211_TX_POWER_LIMITED (allow using less than + * specified from userspace), whereas TPC is disabled if + * nl80211_tx_power_setting is set to %NL80211_TX_POWER_FIXED * * @chandef: the channel definition to tune to * @radar_enabled: whether radar detection is enabled @@ -1135,6 +1144,7 @@ enum ieee80211_smps_mode { struct ieee80211_conf { u32 flags; int power_level, dynamic_ps_timeout; + bool tpc_enabled; int max_sleep_period; u16 listen_interval; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e75d5c5..05829d5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2118,6 +2118,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, break; } + sdata->tx_power_type = type; + ieee80211_recalc_txpower(sdata); return 0; @@ -2136,8 +2138,10 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, } mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) + list_for_each_entry(sdata, &local->interfaces, list) { sdata->user_power_level = local->user_power_level; + sdata->tx_power_type = type; + } list_for_each_entry(sdata, &local->interfaces, list) ieee80211_recalc_txpower(sdata); mutex_unlock(&local->iflist_mtx); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cc6e964..0c6c7a4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -869,6 +869,7 @@ struct ieee80211_sub_if_data { int user_power_level; /* in dBm */ int ap_power_level; /* in dBm */ + enum nl80211_tx_power_setting tx_power_type; bool radar_required; struct delayed_work dfs_cac_timer_work; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 538fe4e..33277e2 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -47,6 +47,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) { struct ieee80211_chanctx_conf *chanctx_conf; int power; + bool tpc_enabled; rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); @@ -64,8 +65,13 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) power = min(power, sdata->ap_power_level); - if (power != sdata->vif.bss_conf.txpower) { + tpc_enabled = (sdata->tx_power_type == NL80211_TX_POWER_AUTOMATIC || + sdata->tx_power_type == NL80211_TX_POWER_LIMITED); + + if (power != sdata->vif.bss_conf.txpower || + tpc_enabled != sdata->vif.bss_conf.tpc_enabled) { sdata->vif.bss_conf.txpower = power; + sdata->vif.bss_conf.tpc_enabled = tpc_enabled; ieee80211_hw_config(sdata->local, 0); return true; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6ab99da..bfcaeee 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -100,6 +100,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) u32 changed = 0; int power; u32 offchannel_flag; + bool tpc_enabled = false; offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; @@ -152,12 +153,17 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) continue; power = min(power, sdata->vif.bss_conf.txpower); + + if (!tpc_enabled && sdata->vif.bss_conf.tpc_enabled) + tpc_enabled = true; } rcu_read_unlock(); - if (local->hw.conf.power_level != power) { + if (local->hw.conf.power_level != power || + local->hw.conf.tpc_enabled != tpc_enabled) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; + local->hw.conf.tpc_enabled = tpc_enabled; } return changed; -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html