aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/main.c10
-rw-r--r--net/mac80211/mlme.c9
-rw-r--r--net/mac80211/spectmgmt.c21
4 files changed, 42 insertions, 2 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9112c5247c35..c9ffadb55d36 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -715,6 +715,7 @@ struct ieee80211_local {
715 struct timer_list dynamic_ps_timer; 715 struct timer_list dynamic_ps_timer;
716 716
717 int user_power_level; /* in dBm */ 717 int user_power_level; /* in dBm */
718 int power_constr_level; /* in dBm */
718 719
719#ifdef CONFIG_MAC80211_DEBUGFS 720#ifdef CONFIG_MAC80211_DEBUGFS
720 struct local_debugfsdentries { 721 struct local_debugfsdentries {
@@ -985,6 +986,9 @@ void ieee80211_chswitch_work(struct work_struct *work);
985void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, 986void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
986 struct ieee80211_channel_sw_ie *sw_elem, 987 struct ieee80211_channel_sw_ie *sw_elem,
987 struct ieee80211_bss *bss); 988 struct ieee80211_bss *bss);
989void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
990 u16 capab_info, u8 *pwr_constr_elem,
991 u8 pwr_constr_elem_len);
988 992
989/* utility functions/constants */ 993/* utility functions/constants */
990extern void *mac80211_wiphy_privid; /* for wiphy privid */ 994extern void *mac80211_wiphy_privid; /* for wiphy privid */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index e9f3e85d1a9e..c78304db475e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -214,10 +214,16 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
214 changed |= IEEE80211_CONF_CHANGE_CHANNEL; 214 changed |= IEEE80211_CONF_CHANGE_CHANNEL;
215 } 215 }
216 216
217 if (!local->user_power_level) 217 if (local->sw_scanning)
218 power = chan->max_power; 218 power = chan->max_power;
219 else 219 else
220 power = min(chan->max_power, local->user_power_level); 220 power = local->power_constr_level ?
221 (chan->max_power - local->power_constr_level) :
222 chan->max_power;
223
224 if (local->user_power_level)
225 power = min(power, local->user_power_level);
226
221 if (local->hw.conf.power_level != power) { 227 if (local->hw.conf.power_level != power) {
222 changed |= IEEE80211_CONF_CHANGE_POWER; 228 changed |= IEEE80211_CONF_CHANGE_POWER;
223 local->hw.conf.power_level = power; 229 local->hw.conf.power_level = power;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 82c598a83687..f0d42498c257 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -905,6 +905,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
905 /* channel(_type) changes are handled by ieee80211_hw_config */ 905 /* channel(_type) changes are handled by ieee80211_hw_config */
906 local->oper_channel_type = NL80211_CHAN_NO_HT; 906 local->oper_channel_type = NL80211_CHAN_NO_HT;
907 907
908 local->power_constr_level = 0;
909
908 del_timer_sync(&local->dynamic_ps_timer); 910 del_timer_sync(&local->dynamic_ps_timer);
909 cancel_work_sync(&local->dynamic_ps_enable_work); 911 cancel_work_sync(&local->dynamic_ps_enable_work);
910 912
@@ -1849,6 +1851,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1849 * for the BSSID we are associated to */ 1851 * for the BSSID we are associated to */
1850 regulatory_hint_11d(local->hw.wiphy, 1852 regulatory_hint_11d(local->hw.wiphy,
1851 elems.country_elem, elems.country_elem_len); 1853 elems.country_elem, elems.country_elem_len);
1854
1855 /* TODO: IBSS also needs this */
1856 if (elems.pwr_constr_elem)
1857 ieee80211_handle_pwr_constr(sdata,
1858 le16_to_cpu(mgmt->u.probe_resp.capab_info),
1859 elems.pwr_constr_elem,
1860 elems.pwr_constr_elem_len);
1852 } 1861 }
1853 1862
1854 ieee80211_bss_info_change_notify(sdata, changed); 1863 ieee80211_bss_info_change_notify(sdata, changed);
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 8396b5a77e8d..8d4ec2968f8f 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -161,3 +161,24 @@ void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
161 jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int)); 161 jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int));
162 } 162 }
163} 163}
164
165void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
166 u16 capab_info, u8 *pwr_constr_elem,
167 u8 pwr_constr_elem_len)
168{
169 struct ieee80211_conf *conf = &sdata->local->hw.conf;
170
171 if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
172 return;
173
174 /* Power constraint IE length should be 1 octet */
175 if (pwr_constr_elem_len != 1)
176 return;
177
178 if ((*pwr_constr_elem <= conf->channel->max_power) &&
179 (*pwr_constr_elem != sdata->local->power_constr_level)) {
180 sdata->local->power_constr_level = *pwr_constr_elem;
181 ieee80211_hw_config(sdata->local, 0);
182 }
183}
184