Commit 24a4e400 authored by Steinar H. Gunderson's avatar Steinar H. Gunderson Committed by Johannes Berg

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: default avatarSteinar H. Gunderson <sgunderson@bigfoot.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f3000e1b
...@@ -1171,19 +1171,21 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -1171,19 +1171,21 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
} }
static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, static bool
struct ieee80211_channel *channel, ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
const u8 *country_ie, u8 country_ie_len, struct ieee80211_channel *channel,
const u8 *pwr_constr_elem) const u8 *country_ie, u8 country_ie_len,
const u8 *pwr_constr_elem,
int *chan_pwr, int *pwr_reduction)
{ {
struct ieee80211_country_ie_triplet *triplet; struct ieee80211_country_ie_triplet *triplet;
int chan = ieee80211_frequency_to_channel(channel->center_freq); int chan = ieee80211_frequency_to_channel(channel->center_freq);
int i, chan_pwr, chan_increment, new_ap_level; int i, chan_increment;
bool have_chan_pwr = false; bool have_chan_pwr = false;
/* Invalid IE */ /* Invalid IE */
if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
return 0; return false;
triplet = (void *)(country_ie + 3); triplet = (void *)(country_ie + 3);
country_ie_len -= 3; country_ie_len -= 3;
...@@ -1211,7 +1213,7 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, ...@@ -1211,7 +1213,7 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < triplet->chans.num_channels; i++) { for (i = 0; i < triplet->chans.num_channels; i++) {
if (first_channel + i * chan_increment == chan) { if (first_channel + i * chan_increment == chan) {
have_chan_pwr = true; have_chan_pwr = true;
chan_pwr = triplet->chans.max_power; *chan_pwr = triplet->chans.max_power;
break; break;
} }
} }
...@@ -1223,18 +1225,41 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, ...@@ -1223,18 +1225,41 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
country_ie_len -= 3; country_ie_len -= 3;
} }
if (!have_chan_pwr) if (have_chan_pwr)
return 0; *pwr_reduction = *pwr_constr_elem;
return have_chan_pwr;
}
static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel,
struct ieee80211_mgmt *mgmt,
const u8 *country_ie, u8 country_ie_len,
const u8 *pwr_constr_ie)
{
bool has_80211h_pwr = false;
int chan_pwr, pwr_reduction_80211h;
int new_ap_level;
new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); if (country_ie && pwr_constr_ie &&
mgmt->u.probe_resp.capab_info &
cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) {
has_80211h_pwr = ieee80211_find_80211h_pwr_constr(
sdata, channel, country_ie, country_ie_len,
pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h);
new_ap_level = max_t(int, 0, chan_pwr - pwr_reduction_80211h);
}
if (sdata->ap_power_level == new_ap_level) if (!has_80211h_pwr)
return 0; return 0;
sdata_info(sdata, sdata_info(sdata,
"Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
new_ap_level, chan_pwr, *pwr_constr_elem, new_ap_level, chan_pwr, pwr_reduction_80211h,
sdata->u.mgd.bssid); sdata->u.mgd.bssid);
if (sdata->ap_power_level == new_ap_level)
return 0;
sdata->ap_power_level = new_ap_level; sdata->ap_power_level = new_ap_level;
if (__ieee80211_recalc_txpower(sdata)) if (__ieee80211_recalc_txpower(sdata))
return BSS_CHANGED_TXPOWER; return BSS_CHANGED_TXPOWER;
...@@ -3204,13 +3229,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -3204,13 +3229,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
rx_status->band, true); rx_status->band, true);
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
if (elems.country_elem && elems.pwr_constr_elem && changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
mgmt->u.probe_resp.capab_info & elems.country_elem,
cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) elems.country_elem_len,
changed |= ieee80211_handle_pwr_constr(sdata, chan, elems.pwr_constr_elem);
elems.country_elem,
elems.country_elem_len,
elems.pwr_constr_elem);
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment