aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h7
-rw-r--r--net/mac80211/cfg.c47
-rw-r--r--net/mac80211/chan.c2
-rw-r--r--net/mac80211/debugfs_netdev.c6
-rw-r--r--net/mac80211/ieee80211_i.h12
-rw-r--r--net/mac80211/iface.c38
-rw-r--r--net/mac80211/main.c27
-rw-r--r--net/mac80211/mlme.c32
-rw-r--r--net/mac80211/trace.h2
-rw-r--r--net/mac80211/util.c3
10 files changed, 131 insertions, 45 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5f5327452c9a..dfa589b721b6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -207,6 +207,7 @@ struct ieee80211_chanctx_conf {
207 * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode) 207 * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
208 * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode) 208 * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
209 * @BSS_CHANGED_PS: PS changed for this BSS (STA mode) 209 * @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
210 * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
210 */ 211 */
211enum ieee80211_bss_change { 212enum ieee80211_bss_change {
212 BSS_CHANGED_ASSOC = 1<<0, 213 BSS_CHANGED_ASSOC = 1<<0,
@@ -227,6 +228,7 @@ enum ieee80211_bss_change {
227 BSS_CHANGED_SSID = 1<<15, 228 BSS_CHANGED_SSID = 1<<15,
228 BSS_CHANGED_AP_PROBE_RESP = 1<<16, 229 BSS_CHANGED_AP_PROBE_RESP = 1<<16,
229 BSS_CHANGED_PS = 1<<17, 230 BSS_CHANGED_PS = 1<<17,
231 BSS_CHANGED_TXPOWER = 1<<18,
230 232
231 /* when adding here, make sure to change ieee80211_reconfig */ 233 /* when adding here, make sure to change ieee80211_reconfig */
232}; 234};
@@ -309,6 +311,7 @@ enum ieee80211_rssi_event {
309 * @ssid: The SSID of the current vif. Only valid in AP-mode. 311 * @ssid: The SSID of the current vif. Only valid in AP-mode.
310 * @ssid_len: Length of SSID given in @ssid. 312 * @ssid_len: Length of SSID given in @ssid.
311 * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode. 313 * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
314 * @txpower: TX power in dBm
312 */ 315 */
313struct ieee80211_bss_conf { 316struct ieee80211_bss_conf {
314 const u8 *bssid; 317 const u8 *bssid;
@@ -341,6 +344,7 @@ struct ieee80211_bss_conf {
341 u8 ssid[IEEE80211_MAX_SSID_LEN]; 344 u8 ssid[IEEE80211_MAX_SSID_LEN];
342 size_t ssid_len; 345 size_t ssid_len;
343 bool hidden_ssid; 346 bool hidden_ssid;
347 int txpower;
344}; 348};
345 349
346/** 350/**
@@ -884,7 +888,8 @@ enum ieee80211_smps_mode {
884 * powersave documentation below. This variable is valid only when 888 * powersave documentation below. This variable is valid only when
885 * the CONF_PS flag is set. 889 * the CONF_PS flag is set.
886 * 890 *
887 * @power_level: requested transmit power (in dBm) 891 * @power_level: requested transmit power (in dBm), backward compatibility
892 * value only that is set to the minimum of all interfaces
888 * 893 *
889 * @channel: the channel to tune to 894 * @channel: the channel to tune to
890 * @channel_type: the channel (HT) type 895 * @channel_type: the channel (HT) type
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a352e4d22dd9..986e9a139d42 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1996,33 +1996,46 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
1996 enum nl80211_tx_power_setting type, int mbm) 1996 enum nl80211_tx_power_setting type, int mbm)
1997{ 1997{
1998 struct ieee80211_local *local = wiphy_priv(wiphy); 1998 struct ieee80211_local *local = wiphy_priv(wiphy);
1999 struct ieee80211_channel *chan = local->_oper_channel; 1999 struct ieee80211_sub_if_data *sdata;
2000 u32 changes = 0;
2001 2000
2002 /* FIXME */ 2001 if (wdev) {
2003 if (local->use_chanctx) 2002 sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
2004 return -EOPNOTSUPP; 2003
2004 switch (type) {
2005 case NL80211_TX_POWER_AUTOMATIC:
2006 sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
2007 break;
2008 case NL80211_TX_POWER_LIMITED:
2009 case NL80211_TX_POWER_FIXED:
2010 if (mbm < 0 || (mbm % 100))
2011 return -EOPNOTSUPP;
2012 sdata->user_power_level = MBM_TO_DBM(mbm);
2013 break;
2014 }
2015
2016 ieee80211_recalc_txpower(sdata);
2017
2018 return 0;
2019 }
2005 2020
2006 switch (type) { 2021 switch (type) {
2007 case NL80211_TX_POWER_AUTOMATIC: 2022 case NL80211_TX_POWER_AUTOMATIC:
2008 local->user_power_level = -1; 2023 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
2009 break; 2024 break;
2010 case NL80211_TX_POWER_LIMITED: 2025 case NL80211_TX_POWER_LIMITED:
2011 if (mbm < 0 || (mbm % 100))
2012 return -EOPNOTSUPP;
2013 local->user_power_level = MBM_TO_DBM(mbm);
2014 break;
2015 case NL80211_TX_POWER_FIXED: 2026 case NL80211_TX_POWER_FIXED:
2016 if (mbm < 0 || (mbm % 100)) 2027 if (mbm < 0 || (mbm % 100))
2017 return -EOPNOTSUPP; 2028 return -EOPNOTSUPP;
2018 /* TODO: move to cfg80211 when it knows the channel */
2019 if (MBM_TO_DBM(mbm) > chan->max_power)
2020 return -EINVAL;
2021 local->user_power_level = MBM_TO_DBM(mbm); 2029 local->user_power_level = MBM_TO_DBM(mbm);
2022 break; 2030 break;
2023 } 2031 }
2024 2032
2025 ieee80211_hw_config(local, changes); 2033 mutex_lock(&local->iflist_mtx);
2034 list_for_each_entry(sdata, &local->interfaces, list)
2035 sdata->user_power_level = local->user_power_level;
2036 list_for_each_entry(sdata, &local->interfaces, list)
2037 ieee80211_recalc_txpower(sdata);
2038 mutex_unlock(&local->iflist_mtx);
2026 2039
2027 return 0; 2040 return 0;
2028} 2041}
@@ -2032,8 +2045,12 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
2032 int *dbm) 2045 int *dbm)
2033{ 2046{
2034 struct ieee80211_local *local = wiphy_priv(wiphy); 2047 struct ieee80211_local *local = wiphy_priv(wiphy);
2048 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
2035 2049
2036 *dbm = local->hw.conf.power_level; 2050 if (!local->use_chanctx)
2051 *dbm = local->hw.conf.power_level;
2052 else
2053 *dbm = sdata->vif.bss_conf.txpower;
2037 2054
2038 return 0; 2055 return 0;
2039} 2056}
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index f84b86028a9c..a2b06d40aebf 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -173,6 +173,8 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
173 rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf); 173 rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
174 ctx->refcount++; 174 ctx->refcount++;
175 175
176 ieee80211_recalc_txpower(sdata);
177
176 return 0; 178 return 0;
177} 179}
178 180
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 3393ad5b8ab1..07c5721323ca 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -168,6 +168,9 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
168IEEE80211_IF_FILE(flags, flags, HEX); 168IEEE80211_IF_FILE(flags, flags, HEX);
169IEEE80211_IF_FILE(state, state, LHEX); 169IEEE80211_IF_FILE(state, state, LHEX);
170IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); 170IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
171IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
172IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
173IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
171 174
172/* STA attributes */ 175/* STA attributes */
173IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); 176IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
@@ -632,6 +635,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
632 DEBUGFS_ADD(flags); 635 DEBUGFS_ADD(flags);
633 DEBUGFS_ADD(state); 636 DEBUGFS_ADD(state);
634 DEBUGFS_ADD(channel_type); 637 DEBUGFS_ADD(channel_type);
638 DEBUGFS_ADD(txpower);
639 DEBUGFS_ADD(user_power_level);
640 DEBUGFS_ADD(ap_power_level);
635 641
636 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) 642 if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
637 add_common_files(sdata); 643 add_common_files(sdata);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3026519b236a..a1f7c139308e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -56,6 +56,9 @@ struct ieee80211_local;
56#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) 56#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
57#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) 57#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
58 58
59/* power level hasn't been configured (or set to automatic) */
60#define IEEE80211_UNSET_POWER_LEVEL INT_MIN
61
59/* 62/*
60 * Some APs experience problems when working with U-APSD. Decrease the 63 * Some APs experience problems when working with U-APSD. Decrease the
61 * probability of that happening by using legacy mode for all ACs but VO. 64 * probability of that happening by using legacy mode for all ACs but VO.
@@ -743,6 +746,9 @@ struct ieee80211_sub_if_data {
743 u8 needed_rx_chains; 746 u8 needed_rx_chains;
744 enum ieee80211_smps_mode smps_mode; 747 enum ieee80211_smps_mode smps_mode;
745 748
749 int user_power_level; /* in dBm */
750 int ap_power_level; /* in dBm */
751
746 /* 752 /*
747 * AP this belongs to: self in AP mode and 753 * AP this belongs to: self in AP mode and
748 * corresponding AP in VLAN mode, NULL for 754 * corresponding AP in VLAN mode, NULL for
@@ -1117,8 +1123,7 @@ struct ieee80211_local {
1117 int dynamic_ps_user_timeout; 1123 int dynamic_ps_user_timeout;
1118 bool disable_dynamic_ps; 1124 bool disable_dynamic_ps;
1119 1125
1120 int user_power_level; /* in dBm */ 1126 int user_power_level; /* in dBm, for all interfaces */
1121 int ap_power_level; /* in dBm */
1122 1127
1123 enum ieee80211_smps_mode smps_mode; 1128 enum ieee80211_smps_mode smps_mode;
1124 1129
@@ -1365,6 +1370,9 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
1365int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); 1370int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up);
1366void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); 1371void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
1367 1372
1373bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
1374void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
1375
1368static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) 1376static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
1369{ 1377{
1370 return test_bit(SDATA_STATE_RUNNING, &sdata->state); 1378 return test_bit(SDATA_STATE_RUNNING, &sdata->state);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1a6fe135f201..80ce90b29d9d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -42,6 +42,41 @@
42 * by either the RTNL, the iflist_mtx or RCU. 42 * by either the RTNL, the iflist_mtx or RCU.
43 */ 43 */
44 44
45bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
46{
47 struct ieee80211_chanctx_conf *chanctx_conf;
48 int power;
49
50 rcu_read_lock();
51 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
52 if (!chanctx_conf) {
53 rcu_read_unlock();
54 return false;
55 }
56
57 power = chanctx_conf->channel->max_power;
58 rcu_read_unlock();
59
60 if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
61 power = min(power, sdata->user_power_level);
62
63 if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
64 power = min(power, sdata->ap_power_level);
65
66 if (power != sdata->vif.bss_conf.txpower) {
67 sdata->vif.bss_conf.txpower = power;
68 ieee80211_hw_config(sdata->local, 0);
69 return true;
70 }
71
72 return false;
73}
74
75void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
76{
77 if (__ieee80211_recalc_txpower(sdata))
78 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
79}
45 80
46static u32 ieee80211_idle_off(struct ieee80211_local *local, 81static u32 ieee80211_idle_off(struct ieee80211_local *local,
47 const char *reason) 82 const char *reason)
@@ -1510,6 +1545,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1510 1545
1511 ieee80211_set_default_queues(sdata); 1546 ieee80211_set_default_queues(sdata);
1512 1547
1548 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1549 sdata->user_power_level = local->user_power_level;
1550
1513 /* setup type-dependent data */ 1551 /* setup type-dependent data */
1514 ieee80211_setup_sdata(sdata, type); 1552 ieee80211_setup_sdata(sdata, type);
1515 1553
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index fd8345c20051..70e87600cacc 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -95,11 +95,13 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
95 95
96static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) 96static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
97{ 97{
98 struct ieee80211_sub_if_data *sdata;
98 struct ieee80211_channel *chan; 99 struct ieee80211_channel *chan;
99 u32 changed = 0; 100 u32 changed = 0;
100 int power; 101 int power;
101 enum nl80211_channel_type channel_type; 102 enum nl80211_channel_type channel_type;
102 u32 offchannel_flag; 103 u32 offchannel_flag;
104 bool scanning = false;
103 105
104 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 106 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
105 if (local->scan_channel) { 107 if (local->scan_channel) {
@@ -146,16 +148,18 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
146 changed |= IEEE80211_CONF_CHANGE_SMPS; 148 changed |= IEEE80211_CONF_CHANGE_SMPS;
147 } 149 }
148 150
149 if (test_bit(SCAN_SW_SCANNING, &local->scanning) || 151 scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
150 test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || 152 test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
151 test_bit(SCAN_HW_SCANNING, &local->scanning) || 153 test_bit(SCAN_HW_SCANNING, &local->scanning);
152 !local->ap_power_level) 154 power = chan->max_power;
153 power = chan->max_power;
154 else
155 power = min(chan->max_power, local->ap_power_level);
156 155
157 if (local->user_power_level >= 0) 156 rcu_read_lock();
158 power = min(power, local->user_power_level); 157 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
158 if (!rcu_access_pointer(sdata->vif.chanctx_conf))
159 continue;
160 power = min(power, sdata->vif.bss_conf.txpower);
161 }
162 rcu_read_unlock();
159 163
160 if (local->hw.conf.power_level != power) { 164 if (local->hw.conf.power_level != power) {
161 changed |= IEEE80211_CONF_CHANGE_POWER; 165 changed |= IEEE80211_CONF_CHANGE_POWER;
@@ -600,7 +604,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
600 604
601 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | 605 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
602 NL80211_FEATURE_SAE | 606 NL80211_FEATURE_SAE |
603 NL80211_FEATURE_HT_IBSS; 607 NL80211_FEATURE_HT_IBSS |
608 NL80211_FEATURE_VIF_TXPOWER;
604 609
605 if (!ops->hw_scan) 610 if (!ops->hw_scan)
606 wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | 611 wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
@@ -633,7 +638,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
633 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | 638 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
634 IEEE80211_RADIOTAP_MCS_HAVE_GI | 639 IEEE80211_RADIOTAP_MCS_HAVE_GI |
635 IEEE80211_RADIOTAP_MCS_HAVE_BW; 640 IEEE80211_RADIOTAP_MCS_HAVE_BW;
636 local->user_power_level = -1; 641 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
637 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; 642 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
638 643
639 INIT_LIST_HEAD(&local->interfaces); 644 INIT_LIST_HEAD(&local->interfaces);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1d1fdf0791f0..d29762fdd887 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -820,10 +820,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
820 cbss->beacon_interval)); 820 cbss->beacon_interval));
821} 821}
822 822
823static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 823static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
824 struct ieee80211_channel *channel, 824 struct ieee80211_channel *channel,
825 const u8 *country_ie, u8 country_ie_len, 825 const u8 *country_ie, u8 country_ie_len,
826 const u8 *pwr_constr_elem) 826 const u8 *pwr_constr_elem)
827{ 827{
828 struct ieee80211_country_ie_triplet *triplet; 828 struct ieee80211_country_ie_triplet *triplet;
829 int chan = ieee80211_frequency_to_channel(channel->center_freq); 829 int chan = ieee80211_frequency_to_channel(channel->center_freq);
@@ -832,7 +832,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
832 832
833 /* Invalid IE */ 833 /* Invalid IE */
834 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 834 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
835 return; 835 return 0;
836 836
837 triplet = (void *)(country_ie + 3); 837 triplet = (void *)(country_ie + 3);
838 country_ie_len -= 3; 838 country_ie_len -= 3;
@@ -873,19 +873,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
873 } 873 }
874 874
875 if (!have_chan_pwr) 875 if (!have_chan_pwr)
876 return; 876 return 0;
877 877
878 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); 878 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
879 879
880 if (sdata->local->ap_power_level == new_ap_level) 880 if (sdata->ap_power_level == new_ap_level)
881 return; 881 return 0;
882 882
883 sdata_info(sdata, 883 sdata_info(sdata,
884 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", 884 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
885 new_ap_level, chan_pwr, *pwr_constr_elem, 885 new_ap_level, chan_pwr, *pwr_constr_elem,
886 sdata->u.mgd.bssid); 886 sdata->u.mgd.bssid);
887 sdata->local->ap_power_level = new_ap_level; 887 sdata->ap_power_level = new_ap_level;
888 ieee80211_hw_config(sdata->local, 0); 888 if (__ieee80211_recalc_txpower(sdata))
889 return BSS_CHANGED_TXPOWER;
890 return 0;
889} 891}
890 892
891void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) 893void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
@@ -1489,7 +1491,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1489 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1491 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1490 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); 1492 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1491 1493
1492 local->ap_power_level = 0; 1494 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1493 1495
1494 del_timer_sync(&local->dynamic_ps_timer); 1496 del_timer_sync(&local->dynamic_ps_timer);
1495 cancel_work_sync(&local->dynamic_ps_enable_work); 1497 cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -2623,10 +2625,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2623 if (elems.country_elem && elems.pwr_constr_elem && 2625 if (elems.country_elem && elems.pwr_constr_elem &&
2624 mgmt->u.probe_resp.capab_info & 2626 mgmt->u.probe_resp.capab_info &
2625 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) 2627 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
2626 ieee80211_handle_pwr_constr(sdata, chan, 2628 changed |= ieee80211_handle_pwr_constr(sdata, chan,
2627 elems.country_elem, 2629 elems.country_elem,
2628 elems.country_elem_len, 2630 elems.country_elem_len,
2629 elems.pwr_constr_elem); 2631 elems.pwr_constr_elem);
2630 2632
2631 ieee80211_bss_info_change_notify(sdata, changed); 2633 ieee80211_bss_info_change_notify(sdata, changed);
2632} 2634}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 5e74e77cba9a..eeebbd9cb888 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -342,6 +342,7 @@ TRACE_EVENT(drv_bss_info_changed,
342 __field(bool, ps); 342 __field(bool, ps);
343 __dynamic_array(u8, ssid, info->ssid_len); 343 __dynamic_array(u8, ssid, info->ssid_len);
344 __field(bool, hidden_ssid); 344 __field(bool, hidden_ssid);
345 __field(int, txpower)
345 ), 346 ),
346 347
347 TP_fast_assign( 348 TP_fast_assign(
@@ -376,6 +377,7 @@ TRACE_EVENT(drv_bss_info_changed,
376 __entry->ps = info->ps; 377 __entry->ps = info->ps;
377 memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); 378 memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
378 __entry->hidden_ssid = info->hidden_ssid; 379 __entry->hidden_ssid = info->hidden_ssid;
380 __entry->txpower = info->txpower;
379 ), 381 ),
380 382
381 TP_printk( 383 TP_printk(
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 6636d3962317..1a511afbdf07 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1478,7 +1478,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1478 BSS_CHANGED_BSSID | 1478 BSS_CHANGED_BSSID |
1479 BSS_CHANGED_CQM | 1479 BSS_CHANGED_CQM |
1480 BSS_CHANGED_QOS | 1480 BSS_CHANGED_QOS |
1481 BSS_CHANGED_IDLE; 1481 BSS_CHANGED_IDLE |
1482 BSS_CHANGED_TXPOWER;
1482 1483
1483 switch (sdata->vif.type) { 1484 switch (sdata->vif.type) {
1484 case NL80211_IFTYPE_STATION: 1485 case NL80211_IFTYPE_STATION: