* @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 {
        size_t ssid_len;
        bool hidden_ssid;
        int txpower;
+       enum nl80211_tx_power_setting txpower_type;
        struct ieee80211_p2p_noa_attr p2p_noa_attr;
 };
 
 
 {
        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);
                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:
                        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;
        }
        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:
        }
 
        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;
 
        }
 
        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);
        }
 
                                ieee80211_bss_info_change_notify(sdata,
                                                                 changed);
 
-                       ieee80211_recalc_txpower(sdata);
+                       ieee80211_recalc_txpower(sdata, false);
                }
 
                ieee80211_recalc_chanctx_chantype(local, ctx);
 
 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)
 {
 
        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);
 }