mac80211: fix beacon IE power constraint handling
SVN-Revision: 33583
This commit is contained in:
parent
c02bd635b2
commit
d3add1f103
15 changed files with 191 additions and 23 deletions
|
@ -386,7 +386,90 @@
|
|||
}
|
||||
--- a/net/mac80211/mlme.c
|
||||
+++ b/net/mac80211/mlme.c
|
||||
@@ -1390,7 +1390,7 @@ static void ieee80211_set_disassoc(struc
|
||||
@@ -818,23 +818,71 @@ void ieee80211_sta_process_chanswitch(st
|
||||
}
|
||||
|
||||
static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
|
||||
- u16 capab_info, u8 *pwr_constr_elem,
|
||||
- u8 pwr_constr_elem_len)
|
||||
+ struct ieee80211_channel *channel,
|
||||
+ const u8 *country_ie, u8 country_ie_len,
|
||||
+ const u8 *pwr_constr_elem)
|
||||
{
|
||||
- struct ieee80211_conf *conf = &sdata->local->hw.conf;
|
||||
+ struct ieee80211_country_ie_triplet *triplet;
|
||||
+ int chan = ieee80211_frequency_to_channel(channel->center_freq);
|
||||
+ int i, chan_pwr, chan_increment, new_ap_level;
|
||||
+ bool have_chan_pwr = false;
|
||||
|
||||
- if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
|
||||
+ /* Invalid IE */
|
||||
+ if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
|
||||
return;
|
||||
|
||||
- /* Power constraint IE length should be 1 octet */
|
||||
- if (pwr_constr_elem_len != 1)
|
||||
- return;
|
||||
+ triplet = (void *)(country_ie + 3);
|
||||
+ country_ie_len -= 3;
|
||||
|
||||
- if ((*pwr_constr_elem <= conf->channel->max_reg_power) &&
|
||||
- (*pwr_constr_elem != sdata->local->power_constr_level)) {
|
||||
- sdata->local->power_constr_level = *pwr_constr_elem;
|
||||
- ieee80211_hw_config(sdata->local, 0);
|
||||
+ switch (channel->band) {
|
||||
+ default:
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ /* fall through */
|
||||
+ case IEEE80211_BAND_2GHZ:
|
||||
+ case IEEE80211_BAND_60GHZ:
|
||||
+ chan_increment = 1;
|
||||
+ break;
|
||||
+ case IEEE80211_BAND_5GHZ:
|
||||
+ chan_increment = 4;
|
||||
+ break;
|
||||
}
|
||||
+
|
||||
+ /* find channel */
|
||||
+ while (country_ie_len >= 3) {
|
||||
+ u8 first_channel = triplet->chans.first_channel;
|
||||
+
|
||||
+ if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID)
|
||||
+ goto next;
|
||||
+
|
||||
+ for (i = 0; i < triplet->chans.num_channels; i++) {
|
||||
+ if (first_channel + i * chan_increment == chan) {
|
||||
+ have_chan_pwr = true;
|
||||
+ chan_pwr = triplet->chans.max_power;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (have_chan_pwr)
|
||||
+ break;
|
||||
+
|
||||
+ next:
|
||||
+ triplet++;
|
||||
+ country_ie_len -= 3;
|
||||
+ }
|
||||
+
|
||||
+ if (!have_chan_pwr)
|
||||
+ return;
|
||||
+
|
||||
+ new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
|
||||
+
|
||||
+ if (sdata->local->ap_power_level == new_ap_level)
|
||||
+ return;
|
||||
+
|
||||
+ sdata_info(sdata,
|
||||
+ "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
|
||||
+ new_ap_level, chan_pwr, *pwr_constr_elem,
|
||||
+ sdata->u.mgd.bssid);
|
||||
+ sdata->local->ap_power_level = new_ap_level;
|
||||
+ ieee80211_hw_config(sdata->local, 0);
|
||||
}
|
||||
|
||||
void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
|
||||
@@ -1390,7 +1438,7 @@ static void ieee80211_set_disassoc(struc
|
||||
sta = sta_info_get(sdata, ifmgd->bssid);
|
||||
if (sta) {
|
||||
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
@ -395,6 +478,38 @@
|
|||
}
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
@@ -1438,7 +1486,7 @@ static void ieee80211_set_disassoc(struc
|
||||
memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
|
||||
memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
|
||||
|
||||
- local->power_constr_level = 0;
|
||||
+ local->ap_power_level = 0;
|
||||
|
||||
del_timer_sync(&local->dynamic_ps_timer);
|
||||
cancel_work_sync(&local->dynamic_ps_enable_work);
|
||||
@@ -2530,15 +2578,13 @@ static void ieee80211_rx_mgmt_beacon(str
|
||||
bssid, true);
|
||||
}
|
||||
|
||||
- /* Note: country IE parsing is done for us by cfg80211 */
|
||||
- if (elems.country_elem) {
|
||||
- /* TODO: IBSS also needs this */
|
||||
- if (elems.pwr_constr_elem)
|
||||
- ieee80211_handle_pwr_constr(sdata,
|
||||
- le16_to_cpu(mgmt->u.probe_resp.capab_info),
|
||||
- elems.pwr_constr_elem,
|
||||
- elems.pwr_constr_elem_len);
|
||||
- }
|
||||
+ if (elems.country_elem && elems.pwr_constr_elem &&
|
||||
+ mgmt->u.probe_resp.capab_info &
|
||||
+ cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
|
||||
+ ieee80211_handle_pwr_constr(sdata, local->oper_channel,
|
||||
+ elems.country_elem,
|
||||
+ elems.country_elem_len,
|
||||
+ elems.pwr_constr_elem);
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
}
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -674,7 +674,7 @@ int __must_check __sta_info_destroy(stru
|
||||
|
@ -422,3 +537,56 @@
|
|||
default:
|
||||
if (channel->band == IEEE80211_BAND_5GHZ) {
|
||||
/* Both sample_freq and chip_freq are 40MHz */
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1062,7 +1062,7 @@ struct ieee80211_local {
|
||||
bool disable_dynamic_ps;
|
||||
|
||||
int user_power_level; /* in dBm */
|
||||
- int power_constr_level; /* in dBm */
|
||||
+ int ap_power_level; /* in dBm */
|
||||
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
|
||||
@@ -1170,7 +1170,6 @@ struct ieee802_11_elems {
|
||||
u8 prep_len;
|
||||
u8 perr_len;
|
||||
u8 country_elem_len;
|
||||
- u8 pwr_constr_elem_len;
|
||||
u8 quiet_elem_len;
|
||||
u8 num_of_quiet_elem; /* can be more the one */
|
||||
u8 timeout_int_len;
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -792,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
||||
elems->country_elem_len = elen;
|
||||
break;
|
||||
case WLAN_EID_PWR_CONSTRAINT:
|
||||
+ if (elen != 1) {
|
||||
+ elem_parse_failed = true;
|
||||
+ break;
|
||||
+ }
|
||||
elems->pwr_constr_elem = pos;
|
||||
- elems->pwr_constr_elem_len = elen;
|
||||
break;
|
||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||
elems->timeout_int = pos;
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -154,13 +154,11 @@ int ieee80211_hw_config(struct ieee80211
|
||||
|
||||
if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
|
||||
test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
|
||||
- test_bit(SCAN_HW_SCANNING, &local->scanning))
|
||||
+ test_bit(SCAN_HW_SCANNING, &local->scanning) ||
|
||||
+ !local->ap_power_level)
|
||||
power = chan->max_power;
|
||||
else
|
||||
- power = local->power_constr_level ?
|
||||
- min(chan->max_power,
|
||||
- (chan->max_reg_power - local->power_constr_level)) :
|
||||
- chan->max_power;
|
||||
+ power = min(chan->max_power, local->ap_power_level);
|
||||
|
||||
if (local->user_power_level >= 0)
|
||||
power = min(power, local->user_power_level);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <asm/unaligned.h>
|
||||
|
||||
#include "hw.h"
|
||||
@@ -523,8 +524,16 @@ static int ath9k_hw_init_macaddr(struct
|
||||
@@ -523,8 +524,16 @@ static int ath9k_hw_init_macaddr(struct
|
||||
common->macaddr[2 * i] = eeval >> 8;
|
||||
common->macaddr[2 * i + 1] = eeval & 0xff;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
@@ -89,13 +89,8 @@ ath5k_add_interface(struct ieee80211_hw
|
||||
@@ -89,13 +89,8 @@ ath5k_add_interface(struct ieee80211_hw
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -794,17 +794,11 @@ int ieee80211_register_hw(struct ieee802
|
||||
@@ -792,17 +792,11 @@ int ieee80211_register_hw(struct ieee802
|
||||
*/
|
||||
for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
|
||||
const struct ieee80211_iface_combination *c;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
static bool
|
||||
ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
|
||||
@@ -82,6 +83,19 @@ ath5k_pci_eeprom_read(struct ath_common
|
||||
@@ -82,6 +83,19 @@ ath5k_pci_eeprom_read(struct ath_common
|
||||
struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
|
||||
u32 status, timeout;
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++
|
|||
|
||||
/* debugfs: queues etc */
|
||||
|
||||
@@ -904,6 +987,9 @@ ath5k_debug_init_device(struct ath5k_hw
|
||||
@@ -904,6 +987,9 @@ ath5k_debug_init_device(struct ath5k_hw
|
||||
debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
|
||||
&fops_beacon);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -167,6 +167,7 @@ int ieee80211_hw_config(struct ieee80211
|
||||
@@ -165,6 +165,7 @@ int ieee80211_hw_config(struct ieee80211
|
||||
|
||||
if (local->hw.conf.power_level != power) {
|
||||
changed |= IEEE80211_CONF_CHANGE_POWER;
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
|
||||
@@ -458,12 +458,12 @@ int ath9k_hw_process_rxdesc_edma(struct
|
||||
@@ -458,12 +458,12 @@ int ath9k_hw_process_rxdesc_edma(struct
|
||||
|
||||
/* XXX: Keycache */
|
||||
rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
|
||||
|
@ -227,7 +227,7 @@
|
|||
if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -997,12 +997,12 @@ void ath_debug_stat_rx(struct ath_softc
|
||||
@@ -997,12 +997,12 @@ void ath_debug_stat_rx(struct ath_softc
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
spin_lock(&sc->debug.samp_lock);
|
||||
RX_SAMP_DBG(jiffies) = jiffies;
|
||||
|
@ -363,7 +363,7 @@
|
|||
* hardware stores this as 8 bit signed value.
|
||||
--- a/drivers/net/wireless/ath/ath9k/antenna.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/antenna.c
|
||||
@@ -529,14 +529,14 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
@@ -529,14 +529,14 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
struct ath_ant_comb *antcomb = &sc->ant_comb;
|
||||
int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
|
||||
int curr_main_set;
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -811,7 +811,7 @@ int ath9k_init_device(u16 devid, struct
|
||||
@@ -811,7 +811,7 @@ int ath9k_init_device(u16 devid, struct
|
||||
|
||||
#ifdef CONFIG_MAC80211_LEDS
|
||||
/* must be initialized before ieee80211_register_hw */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||
@@ -689,7 +689,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
|
||||
@@ -689,7 +689,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
|
||||
{
|
||||
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
@ -9,7 +9,7 @@
|
|||
int i;
|
||||
|
||||
/* Enable access to the DMA observation bus */
|
||||
@@ -719,6 +719,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
|
||||
@@ -719,6 +719,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
|
||||
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
@@ -89,20 +89,10 @@ static void rt2800pci_mcu_status(struct
|
||||
@@ -89,20 +89,10 @@ static void rt2800pci_mcu_status(struct
|
||||
rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
|
||||
}
|
||||
|
||||
|
@ -198,12 +198,12 @@
|
|||
- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
|
||||
-
|
||||
- iounmap(base_addr);
|
||||
-}
|
||||
+ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
|
||||
}
|
||||
-#else
|
||||
-static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
+ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
|
||||
}
|
||||
-}
|
||||
-#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
@@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct
|
||||
@@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct
|
||||
rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
}
|
||||
|
||||
static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
|
||||
@@ -2961,11 +3038,15 @@ static int rt2800_init_registers(struct
|
||||
@@ -2961,11 +3038,15 @@ static int rt2800_init_registers(struct
|
||||
if (rt2x00_rt(rt2x00dev, RT3071) ||
|
||||
rt2x00_rt(rt2x00dev, RT3090) ||
|
||||
rt2x00_rt(rt2x00dev, RT3290) ||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
BCMA_CORETABLE_END
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -734,7 +734,7 @@ static void brcms_c_ucode_bsinit(struct
|
||||
@@ -734,7 +734,7 @@ static void brcms_c_ucode_bsinit(struct
|
||||
brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
|
||||
|
||||
/* do band-specific ucode IHR, SHM, and SCR inits */
|
||||
|
@ -19,7 +19,7 @@
|
|||
if (BRCMS_ISNPHY(wlc_hw->band))
|
||||
brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
|
||||
else
|
||||
@@ -2259,7 +2259,7 @@ static void brcms_ucode_download(struct
|
||||
@@ -2259,7 +2259,7 @@ static void brcms_ucode_download(struct
|
||||
if (wlc_hw->ucode_loaded)
|
||||
return;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -734,7 +734,7 @@ static void brcms_c_ucode_bsinit(struct
|
||||
@@ -734,7 +734,7 @@ static void brcms_c_ucode_bsinit(struct
|
||||
brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
|
||||
|
||||
/* do band-specific ucode IHR, SHM, and SCR inits */
|
||||
|
@ -19,7 +19,7 @@
|
|||
if (BRCMS_ISNPHY(wlc_hw->band))
|
||||
brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
|
||||
else
|
||||
@@ -2259,7 +2259,7 @@ static void brcms_ucode_download(struct
|
||||
@@ -2259,7 +2259,7 @@ static void brcms_ucode_download(struct
|
||||
if (wlc_hw->ucode_loaded)
|
||||
return;
|
||||
|
||||
|
|
Loading…
Reference in a new issue