Control 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 <[email protected]>
---
include/net/mac80211.h | 8 ++++++++
net/mac80211/cfg.c | 16 +++++++++++++---
net/mac80211/chan.c | 4 ++--
net/mac80211/ieee80211_i.h | 3 ++-
net/mac80211/iface.c | 5 +++--
5 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 58d719d..7d705c2 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -376,6 +376,13 @@ 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
+ * @txpower_type: TX power adjustment used to control per packet Transmit
+ * Power Control (TPC) in lower driver for the current vif. In particular
+ * TPC is enabled if value passed in %txpower_type 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 %txpower_type is set to
+ * NL80211_TX_POWER_FIXED (use value configured from userspace)
* @p2p_noa_attr: P2P NoA attribute for P2P powersave
*/
struct ieee80211_bss_conf {
@@ -411,6 +418,7 @@ struct ieee80211_bss_conf {
size_t ssid_len;
bool hidden_ssid;
int txpower;
+ enum nl80211_tx_power_setting txpower_type;
struct ieee80211_p2p_noa_attr p2p_noa_attr;
};
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e75d5c5..7f28783 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2102,6 +2102,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
+ bool update_tpc = false;
if (wdev) {
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
@@ -2118,7 +2119,12 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
break;
}
- ieee80211_recalc_txpower(sdata);
+ if (type != sdata->vif.bss_conf.txpower_type) {
+ update_tpc = true;
+ sdata->vif.bss_conf.txpower_type = type;
+ }
+
+ ieee80211_recalc_txpower(sdata, update_tpc);
return 0;
}
@@ -2136,10 +2142,14 @@ 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;
+ if (!update_tpc && type != sdata->vif.bss_conf.txpower_type)
+ update_tpc = true;
+ sdata->vif.bss_conf.txpower_type = type;
+ }
list_for_each_entry(sdata, &local->interfaces, list)
- ieee80211_recalc_txpower(sdata);
+ ieee80211_recalc_txpower(sdata, update_tpc);
mutex_unlock(&local->iflist_mtx);
return 0;
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index da1c12c..17c49d8 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -628,7 +628,7 @@ out:
}
if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
- ieee80211_recalc_txpower(sdata);
+ ieee80211_recalc_txpower(sdata, false);
ieee80211_recalc_chanctx_min_def(local, new_ctx);
}
@@ -1360,7 +1360,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(sdata,
changed);
- ieee80211_recalc_txpower(sdata);
+ ieee80211_recalc_txpower(sdata, false);
}
ieee80211_recalc_chanctx_chantype(local, ctx);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cc6e964..0815ffc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1623,7 +1623,8 @@ 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);
-void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
+void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
+ bool update_bss);
static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 4173553..bc885e2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -73,9 +73,10 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
return false;
}
-void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
+ bool update_bss)
{
- if (__ieee80211_recalc_txpower(sdata))
+ if (__ieee80211_recalc_txpower(sdata) || update_bss)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
}
--
2.1.0
> On Wed, 2014-12-24 at 10:21 +0100, Lorenzo Bianconi wrote:
>> - list_for_each_entry(sdata, &local->interfaces, list)
>> + list_for_each_entry(sdata, &local->interfaces, list) {
>> sdata->user_power_level = local->user_power_level;
>> + if (!update_tpc && type != sdata->vif.bss_conf.txpower_type)
>> + update_tpc = true;
>
> Why bother checking - if it's already true then setting it to true won't
> matter, and IMHO makes the code easier to read.
>
> I also think "update_tpc" is a bad name - transmit power control is the
> actual usage here, but you really mean "update_txp_type" or so.
>
ack. V4 on the way
> johannes
>
Best regards,
Lorenzo
--
UNIX is Sexy: who | grep -i blonde | talk; cd ~; wine; talk; touch;
unzip; touch; strip; gasp; finger; gasp; mount; fsck; more; yes; gasp;
umount; make clean; sleep
On Wed, 2014-12-24 at 10:21 +0100, Lorenzo Bianconi wrote:
> - list_for_each_entry(sdata, &local->interfaces, list)
> + list_for_each_entry(sdata, &local->interfaces, list) {
> sdata->user_power_level = local->user_power_level;
> + if (!update_tpc && type != sdata->vif.bss_conf.txpower_type)
> + update_tpc = true;
Why bother checking - if it's already true then setting it to true won't
matter, and IMHO makes the code easier to read.
I also think "update_tpc" is a bad name - transmit power control is the
actual usage here, but you really mean "update_txp_type" or so.
johannes