mac80211: enable TPC through mac80211 stack
authorLorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Wed, 14 Jan 2015 11:55:08 +0000 (12:55 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 23 Jan 2015 09:28:51 +0000 (10:28 +0100)
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_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@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c

index 33b87c50a4cfdfe592d6bc72b0ded2b8085f2214..866073e27ea2c8dd55a57eb9846f70c0f23e1408 100644 (file)
@@ -376,6 +376,12 @@ 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_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 +417,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;
 };
 
index ff090ef1ea2cdd57d85484b9f24ec4c801873e3e..a777114d663b4a40bc3306d8615a4fa12a08a687 100644 (file)
@@ -2110,6 +2110,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 {
        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;
 
        if (wdev) {
                sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
@@ -2117,6 +2119,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                switch (type) {
                case NL80211_TX_POWER_AUTOMATIC:
                        sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+                       txp_type = NL80211_TX_POWER_LIMITED;
                        break;
                case NL80211_TX_POWER_LIMITED:
                case NL80211_TX_POWER_FIXED:
@@ -2126,7 +2129,12 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                        break;
                }
 
-               ieee80211_recalc_txpower(sdata);
+               if (txp_type != sdata->vif.bss_conf.txpower_type) {
+                       update_txp_type = true;
+                       sdata->vif.bss_conf.txpower_type = txp_type;
+               }
+
+               ieee80211_recalc_txpower(sdata, update_txp_type);
 
                return 0;
        }
@@ -2134,6 +2142,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
        switch (type) {
        case NL80211_TX_POWER_AUTOMATIC:
                local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+               txp_type = NL80211_TX_POWER_LIMITED;
                break;
        case NL80211_TX_POWER_LIMITED:
        case NL80211_TX_POWER_FIXED:
@@ -2144,10 +2153,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 (txp_type != sdata->vif.bss_conf.txpower_type)
+                       update_txp_type = true;
+               sdata->vif.bss_conf.txpower_type = txp_type;
+       }
        list_for_each_entry(sdata, &local->interfaces, list)
-               ieee80211_recalc_txpower(sdata);
+               ieee80211_recalc_txpower(sdata, update_txp_type);
        mutex_unlock(&local->iflist_mtx);
 
        return 0;
index 35b11e11e0c49ba81cb4ecdc9b3624e02628f503..ff0d2db09df9db467a5831606971e02f2fe6d410 100644 (file)
@@ -655,7 +655,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);
        }
 
@@ -1387,7 +1387,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);
index 156ea79e01579405de37480fdb0797768f675ecf..6e1b184183fb4e5e2b4bfdef2adaf3825c6131e1 100644 (file)
@@ -1621,7 +1621,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)
 {
index 677422e11e075137ce0c85bb6819ce0db17b187b..4371c123a95efca21ef76922995752aa5751ab82 100644 (file)
@@ -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);
 }