summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorSteinar H. Gunderson <sgunderson@bigfoot.com>2014-09-03 09:22:10 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-09-08 04:43:18 -0400
commit24a4e4008ca2a819c4c889163586a8a9b7a3a08d (patch)
treed094dd2bde809c511444636e441af1dc04a112c0 /net/mac80211/mlme.c
parentf3000e1b43f164802f2a74c9de6a398943a36378 (diff)
mac80211: split 802.11h parsing from transmit power policy
Decouple the logic of parsing the 802.11d and 802.11h IEs from the part of deciding what to do about the data (messaging, clamping to 0 dBm, doing the actual setting). This paves the way for the next patch, which introduces more data sources for transmit power limitation. Signed-off-by: Steinar H. Gunderson <sgunderson@bigfoot.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f09bef7ac21d..0b812a88f95f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1171,19 +1171,21 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1171 TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); 1171 TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
1172} 1172}
1173 1173
1174static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 1174static bool
1175 struct ieee80211_channel *channel, 1175ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
1176 const u8 *country_ie, u8 country_ie_len, 1176 struct ieee80211_channel *channel,
1177 const u8 *pwr_constr_elem) 1177 const u8 *country_ie, u8 country_ie_len,
1178 const u8 *pwr_constr_elem,
1179 int *chan_pwr, int *pwr_reduction)
1178{ 1180{
1179 struct ieee80211_country_ie_triplet *triplet; 1181 struct ieee80211_country_ie_triplet *triplet;
1180 int chan = ieee80211_frequency_to_channel(channel->center_freq); 1182 int chan = ieee80211_frequency_to_channel(channel->center_freq);
1181 int i, chan_pwr, chan_increment, new_ap_level; 1183 int i, chan_increment;
1182 bool have_chan_pwr = false; 1184 bool have_chan_pwr = false;
1183 1185
1184 /* Invalid IE */ 1186 /* Invalid IE */
1185 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 1187 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
1186 return 0; 1188 return false;
1187 1189
1188 triplet = (void *)(country_ie + 3); 1190 triplet = (void *)(country_ie + 3);
1189 country_ie_len -= 3; 1191 country_ie_len -= 3;
@@ -1211,7 +1213,7 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1211 for (i = 0; i < triplet->chans.num_channels; i++) { 1213 for (i = 0; i < triplet->chans.num_channels; i++) {
1212 if (first_channel + i * chan_increment == chan) { 1214 if (first_channel + i * chan_increment == chan) {
1213 have_chan_pwr = true; 1215 have_chan_pwr = true;
1214 chan_pwr = triplet->chans.max_power; 1216 *chan_pwr = triplet->chans.max_power;
1215 break; 1217 break;
1216 } 1218 }
1217 } 1219 }
@@ -1223,18 +1225,41 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1223 country_ie_len -= 3; 1225 country_ie_len -= 3;
1224 } 1226 }
1225 1227
1226 if (!have_chan_pwr) 1228 if (have_chan_pwr)
1227 return 0; 1229 *pwr_reduction = *pwr_constr_elem;
1230 return have_chan_pwr;
1231}
1232
1233static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1234 struct ieee80211_channel *channel,
1235 struct ieee80211_mgmt *mgmt,
1236 const u8 *country_ie, u8 country_ie_len,
1237 const u8 *pwr_constr_ie)
1238{
1239 bool has_80211h_pwr = false;
1240 int chan_pwr, pwr_reduction_80211h;
1241 int new_ap_level;
1228 1242
1229 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); 1243 if (country_ie && pwr_constr_ie &&
1244 mgmt->u.probe_resp.capab_info &
1245 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) {
1246 has_80211h_pwr = ieee80211_find_80211h_pwr_constr(
1247 sdata, channel, country_ie, country_ie_len,
1248 pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h);
1249 new_ap_level = max_t(int, 0, chan_pwr - pwr_reduction_80211h);
1250 }
1230 1251
1231 if (sdata->ap_power_level == new_ap_level) 1252 if (!has_80211h_pwr)
1232 return 0; 1253 return 0;
1233 1254
1234 sdata_info(sdata, 1255 sdata_info(sdata,
1235 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", 1256 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
1236 new_ap_level, chan_pwr, *pwr_constr_elem, 1257 new_ap_level, chan_pwr, pwr_reduction_80211h,
1237 sdata->u.mgd.bssid); 1258 sdata->u.mgd.bssid);
1259
1260 if (sdata->ap_power_level == new_ap_level)
1261 return 0;
1262
1238 sdata->ap_power_level = new_ap_level; 1263 sdata->ap_power_level = new_ap_level;
1239 if (__ieee80211_recalc_txpower(sdata)) 1264 if (__ieee80211_recalc_txpower(sdata))
1240 return BSS_CHANGED_TXPOWER; 1265 return BSS_CHANGED_TXPOWER;
@@ -3204,13 +3229,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3204 rx_status->band, true); 3229 rx_status->band, true);
3205 mutex_unlock(&local->sta_mtx); 3230 mutex_unlock(&local->sta_mtx);
3206 3231
3207 if (elems.country_elem && elems.pwr_constr_elem && 3232 changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
3208 mgmt->u.probe_resp.capab_info & 3233 elems.country_elem,
3209 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) 3234 elems.country_elem_len,
3210 changed |= ieee80211_handle_pwr_constr(sdata, chan, 3235 elems.pwr_constr_elem);
3211 elems.country_elem,
3212 elems.country_elem_len,
3213 elems.pwr_constr_elem);
3214 3236
3215 ieee80211_bss_info_change_notify(sdata, changed); 3237 ieee80211_bss_info_change_notify(sdata, changed);
3216} 3238}