diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/main.c | 10 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 9 | ||||
-rw-r--r-- | net/mac80211/spectmgmt.c | 21 |
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); | |||
985 | void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 986 | void 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); |
989 | void 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 */ |
990 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 994 | extern 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 | |||
165 | void 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 | |||