|
|
@@ -2376,10 +2376,17 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
|
|
|
struct ieee80211_sub_if_data *sdata;
|
|
|
enum nl80211_tx_power_setting txp_type = type;
|
|
|
bool update_txp_type = false;
|
|
|
+ bool has_monitor = false;
|
|
|
|
|
|
if (wdev) {
|
|
|
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
|
|
|
|
|
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
|
|
+ sdata = rtnl_dereference(local->monitor_sdata);
|
|
|
+ if (!sdata)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+
|
|
|
switch (type) {
|
|
|
case NL80211_TX_POWER_AUTOMATIC:
|
|
|
sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
|
|
|
@@ -2418,15 +2425,34 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
|
|
|
|
|
|
mutex_lock(&local->iflist_mtx);
|
|
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
|
|
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
|
|
+ has_monitor = true;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
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)
|
|
|
+ list_for_each_entry(sdata, &local->interfaces, list) {
|
|
|
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
|
|
+ continue;
|
|
|
ieee80211_recalc_txpower(sdata, update_txp_type);
|
|
|
+ }
|
|
|
mutex_unlock(&local->iflist_mtx);
|
|
|
|
|
|
+ if (has_monitor) {
|
|
|
+ sdata = rtnl_dereference(local->monitor_sdata);
|
|
|
+ if (sdata) {
|
|
|
+ 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;
|
|
|
+
|
|
|
+ ieee80211_recalc_txpower(sdata, update_txp_type);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|