aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c2
-rw-r--r--include/net/mac80211.h16
-rw-r--r--net/mac80211/debugfs.c4
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c74
-rw-r--r--net/mac80211/util.c4
8 files changed, 63 insertions, 43 deletions
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index ef82751722e0..f293b3ff4756 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1853,7 +1853,7 @@ void *carl9170_alloc(size_t priv_size)
1853 IEEE80211_HW_REPORTS_TX_ACK_STATUS | 1853 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
1854 IEEE80211_HW_SUPPORTS_PS | 1854 IEEE80211_HW_SUPPORTS_PS |
1855 IEEE80211_HW_PS_NULLFUNC_STACK | 1855 IEEE80211_HW_PS_NULLFUNC_STACK |
1856 IEEE80211_HW_NEED_DTIM_PERIOD | 1856 IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
1857 IEEE80211_HW_SIGNAL_DBM; 1857 IEEE80211_HW_SIGNAL_DBM;
1858 1858
1859 if (!modparam_noht) { 1859 if (!modparam_noht) {
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index f1dc04006564..d3cc776d2d34 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5711,7 +5711,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
5711 /* Tell mac80211 our characteristics */ 5711 /* Tell mac80211 our characteristics */
5712 hw->flags = 5712 hw->flags =
5713 IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | 5713 IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
5714 IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | 5714 IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
5715 IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | 5715 IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
5716 IEEE80211_HW_SUPPORTS_DYNAMIC_PS; 5716 IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
5717 if (il->cfg->sku & IL_SKU_N) 5717 if (il->cfg->sku & IL_SKU_N)
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index fa43c0d6abe2..8e5c5c5ce06f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -145,7 +145,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
145 /* Tell mac80211 our characteristics */ 145 /* Tell mac80211 our characteristics */
146 hw->flags = IEEE80211_HW_SIGNAL_DBM | 146 hw->flags = IEEE80211_HW_SIGNAL_DBM |
147 IEEE80211_HW_AMPDU_AGGREGATION | 147 IEEE80211_HW_AMPDU_AGGREGATION |
148 IEEE80211_HW_NEED_DTIM_PERIOD | 148 IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
149 IEEE80211_HW_SPECTRUM_MGMT | 149 IEEE80211_HW_SPECTRUM_MGMT |
150 IEEE80211_HW_REPORTS_TX_ACK_STATUS | 150 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
151 IEEE80211_HW_QUEUE_CONTROL | 151 IEEE80211_HW_QUEUE_CONTROL |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7a27e00c513a..398b6ca4a9c5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -208,6 +208,8 @@ struct ieee80211_chanctx_conf {
208 * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface 208 * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
209 * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS) 209 * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS)
210 * changed (currently only in P2P client mode, GO mode will be later) 210 * changed (currently only in P2P client mode, GO mode will be later)
211 * @BSS_CHANGED_DTIM_PERIOD: the DTIM period value was changed (set when
212 * it becomes valid, managed mode only)
211 */ 213 */
212enum ieee80211_bss_change { 214enum ieee80211_bss_change {
213 BSS_CHANGED_ASSOC = 1<<0, 215 BSS_CHANGED_ASSOC = 1<<0,
@@ -230,6 +232,7 @@ enum ieee80211_bss_change {
230 BSS_CHANGED_PS = 1<<17, 232 BSS_CHANGED_PS = 1<<17,
231 BSS_CHANGED_TXPOWER = 1<<18, 233 BSS_CHANGED_TXPOWER = 1<<18,
232 BSS_CHANGED_P2P_PS = 1<<19, 234 BSS_CHANGED_P2P_PS = 1<<19,
235 BSS_CHANGED_DTIM_PERIOD = 1<<20,
233 236
234 /* when adding here, make sure to change ieee80211_reconfig */ 237 /* when adding here, make sure to change ieee80211_reconfig */
235}; 238};
@@ -271,9 +274,8 @@ enum ieee80211_rssi_event {
271 * if the hardware cannot handle this it must set the 274 * if the hardware cannot handle this it must set the
272 * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag 275 * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
273 * @dtim_period: num of beacons before the next DTIM, for beaconing, 276 * @dtim_period: num of beacons before the next DTIM, for beaconing,
274 * valid in station mode only while @assoc is true and if also 277 * valid in station mode only if after the driver was notified
275 * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf 278 * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then.
276 * @ps_dtim_period)
277 * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old 279 * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old
278 * as it may have been received during scanning long ago) 280 * as it may have been received during scanning long ago)
279 * @sync_device_ts: the device timestamp corresponding to the sync_tsf, 281 * @sync_device_ts: the device timestamp corresponding to the sync_tsf,
@@ -1328,9 +1330,9 @@ struct ieee80211_tx_control {
1328 * When this flag is set, signaling beacon-loss will cause an immediate 1330 * When this flag is set, signaling beacon-loss will cause an immediate
1329 * change to disassociated state. 1331 * change to disassociated state.
1330 * 1332 *
1331 * @IEEE80211_HW_NEED_DTIM_PERIOD: 1333 * @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC:
1332 * This device needs to know the DTIM period for the BSS before 1334 * This device needs to get data from beacon before association (i.e.
1333 * associating. 1335 * dtim_period).
1334 * 1336 *
1335 * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports 1337 * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports
1336 * per-station GTKs as used by IBSS RSN or during fast transition. If 1338 * per-station GTKs as used by IBSS RSN or during fast transition. If
@@ -1375,7 +1377,7 @@ enum ieee80211_hw_flags {
1375 IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, 1377 IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
1376 IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, 1378 IEEE80211_HW_SIGNAL_UNSPEC = 1<<5,
1377 IEEE80211_HW_SIGNAL_DBM = 1<<6, 1379 IEEE80211_HW_SIGNAL_DBM = 1<<6,
1378 IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7, 1380 IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC = 1<<7,
1379 IEEE80211_HW_SPECTRUM_MGMT = 1<<8, 1381 IEEE80211_HW_SPECTRUM_MGMT = 1<<8,
1380 IEEE80211_HW_AMPDU_AGGREGATION = 1<<9, 1382 IEEE80211_HW_AMPDU_AGGREGATION = 1<<9,
1381 IEEE80211_HW_SUPPORTS_PS = 1<<10, 1383 IEEE80211_HW_SUPPORTS_PS = 1<<10,
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 466f4b45dd94..8e6040998ba6 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -121,8 +121,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
121 sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); 121 sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n");
122 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 122 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
123 sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); 123 sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n");
124 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) 124 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC)
125 sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); 125 sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_BEFORE_ASSOC\n");
126 if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) 126 if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)
127 sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); 127 sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n");
128 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) 128 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2f50be7eea09..5ce0b6b6e182 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -399,7 +399,7 @@ struct ieee80211_mgd_assoc_data {
399 u8 ssid_len; 399 u8 ssid_len;
400 u8 supp_rates_len; 400 u8 supp_rates_len;
401 bool wmm, uapsd; 401 bool wmm, uapsd;
402 bool have_beacon; 402 bool have_beacon, need_beacon;
403 bool synced; 403 bool synced;
404 404
405 u8 ap_ht_param; 405 u8 ap_ht_param;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d79b9cd72fc5..a5dba67bbe0b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1445,7 +1445,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1445 1445
1446 ieee80211_led_assoc(local, 1); 1446 ieee80211_led_assoc(local, 1);
1447 1447
1448 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { 1448 if (sdata->u.mgd.assoc_data->have_beacon) {
1449 /* 1449 /*
1450 * If the AP is buggy we may get here with no DTIM period 1450 * If the AP is buggy we may get here with no DTIM period
1451 * known, so assume it's 1 which is the only safe assumption 1451 * known, so assume it's 1 which is the only safe assumption
@@ -1453,6 +1453,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1453 * probably just won't work at all. 1453 * probably just won't work at all.
1454 */ 1454 */
1455 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; 1455 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
1456 bss_info_changed |= BSS_CHANGED_DTIM_PERIOD;
1456 } else { 1457 } else {
1457 bss_conf->dtim_period = 0; 1458 bss_conf->dtim_period = 0;
1458 } 1459 }
@@ -2548,13 +2549,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2548 chan = chanctx_conf->def.chan; 2549 chan = chanctx_conf->def.chan;
2549 rcu_read_unlock(); 2550 rcu_read_unlock();
2550 2551
2551 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && 2552 if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
2552 ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { 2553 ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
2553 ieee802_11_parse_elems(mgmt->u.beacon.variable, 2554 ieee802_11_parse_elems(mgmt->u.beacon.variable,
2554 len - baselen, &elems); 2555 len - baselen, &elems);
2555 2556
2556 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); 2557 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2557 ifmgd->assoc_data->have_beacon = true; 2558 ifmgd->assoc_data->have_beacon = true;
2559 ifmgd->assoc_data->need_beacon = false;
2558 /* continue assoc process */ 2560 /* continue assoc process */
2559 ifmgd->assoc_data->timeout = jiffies; 2561 ifmgd->assoc_data->timeout = jiffies;
2560 run_again(ifmgd, ifmgd->assoc_data->timeout); 2562 run_again(ifmgd, ifmgd->assoc_data->timeout);
@@ -2711,6 +2713,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2711 elems.wmm_param_len)) 2713 elems.wmm_param_len))
2712 changed |= BSS_CHANGED_QOS; 2714 changed |= BSS_CHANGED_QOS;
2713 2715
2716 /*
2717 * If we haven't had a beacon before, tell the driver about the
2718 * DTIM period now.
2719 */
2720 if (!bss_conf->dtim_period) {
2721 /* a few bogus AP send dtim_period = 0 or no TIM IE */
2722 if (elems.tim)
2723 bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
2724 else
2725 bss_conf->dtim_period = 1;
2726 changed |= BSS_CHANGED_DTIM_PERIOD;
2727 }
2728
2714 if (elems.erp_info && elems.erp_info_len >= 1) { 2729 if (elems.erp_info && elems.erp_info_len >= 1) {
2715 erp_valid = true; 2730 erp_valid = true;
2716 erp_value = elems.erp_info[0]; 2731 erp_value = elems.erp_info[0];
@@ -2989,7 +3004,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
2989 3004
2990 if (ifmgd->assoc_data && 3005 if (ifmgd->assoc_data &&
2991 time_after(jiffies, ifmgd->assoc_data->timeout)) { 3006 time_after(jiffies, ifmgd->assoc_data->timeout)) {
2992 if (!ifmgd->assoc_data->have_beacon || 3007 if ((ifmgd->assoc_data->need_beacon &&
3008 !ifmgd->assoc_data->have_beacon) ||
2993 ieee80211_do_assoc(sdata)) { 3009 ieee80211_do_assoc(sdata)) {
2994 u8 bssid[ETH_ALEN]; 3010 u8 bssid[ETH_ALEN];
2995 3011
@@ -3776,6 +3792,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3776 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3792 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3777 struct ieee80211_bss *bss = (void *)req->bss->priv; 3793 struct ieee80211_bss *bss = (void *)req->bss->priv;
3778 struct ieee80211_mgd_assoc_data *assoc_data; 3794 struct ieee80211_mgd_assoc_data *assoc_data;
3795 const struct cfg80211_bss_ies *beacon_ies;
3779 struct ieee80211_supported_band *sband; 3796 struct ieee80211_supported_band *sband;
3780 const u8 *ssidie, *ht_ie, *vht_ie; 3797 const u8 *ssidie, *ht_ie, *vht_ie;
3781 int i, err; 3798 int i, err;
@@ -3941,38 +3958,35 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3941 if (err) 3958 if (err)
3942 goto err_clear; 3959 goto err_clear;
3943 3960
3944 if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { 3961 rcu_read_lock();
3945 const struct cfg80211_bss_ies *beacon_ies; 3962 beacon_ies = rcu_dereference(req->bss->beacon_ies);
3946 3963
3947 rcu_read_lock(); 3964 if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC &&
3948 beacon_ies = rcu_dereference(req->bss->beacon_ies); 3965 !beacon_ies) {
3949 if (!beacon_ies) { 3966 /*
3950 /* 3967 * Wait up to one beacon interval ...
3951 * Wait up to one beacon interval ... 3968 * should this be more if we miss one?
3952 * should this be more if we miss one? 3969 */
3953 */ 3970 sdata_info(sdata, "waiting for beacon from %pM\n",
3954 sdata_info(sdata, "waiting for beacon from %pM\n", 3971 ifmgd->bssid);
3955 ifmgd->bssid); 3972 assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
3956 assoc_data->timeout = 3973 assoc_data->need_beacon = true;
3957 TU_TO_EXP_TIME(req->bss->beacon_interval); 3974 } else if (beacon_ies) {
3958 } else { 3975 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
3959 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, 3976 beacon_ies->data,
3960 beacon_ies->data, 3977 beacon_ies->len);
3961 beacon_ies->len); 3978 if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
3962 if (tim_ie && tim_ie[1] >= 3979 const struct ieee80211_tim_ie *tim;
3963 sizeof(struct ieee80211_tim_ie)) { 3980 tim = (void *)(tim_ie + 2);
3964 const struct ieee80211_tim_ie *tim; 3981 ifmgd->dtim_period = tim->dtim_period;
3965 tim = (void *)(tim_ie + 2);
3966 ifmgd->dtim_period = tim->dtim_period;
3967 }
3968 assoc_data->have_beacon = true;
3969 assoc_data->timeout = jiffies;
3970 } 3982 }
3971 rcu_read_unlock();
3972 } else {
3973 assoc_data->have_beacon = true; 3983 assoc_data->have_beacon = true;
3974 assoc_data->timeout = jiffies; 3984 assoc_data->timeout = jiffies;
3985 } else {
3986 assoc_data->timeout = jiffies;
3975 } 3987 }
3988 rcu_read_unlock();
3989
3976 run_again(ifmgd, assoc_data->timeout); 3990 run_again(ifmgd, assoc_data->timeout);
3977 3991
3978 if (bss->corrupt_data) { 3992 if (bss->corrupt_data) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7519018ff71a..1c74512697f0 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1538,6 +1538,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1538 changed |= BSS_CHANGED_ASSOC | 1538 changed |= BSS_CHANGED_ASSOC |
1539 BSS_CHANGED_ARP_FILTER | 1539 BSS_CHANGED_ARP_FILTER |
1540 BSS_CHANGED_PS; 1540 BSS_CHANGED_PS;
1541
1542 if (sdata->u.mgd.dtim_period)
1543 changed |= BSS_CHANGED_DTIM_PERIOD;
1544
1541 mutex_lock(&sdata->u.mgd.mtx); 1545 mutex_lock(&sdata->u.mgd.mtx);
1542 ieee80211_bss_info_change_notify(sdata, changed); 1546 ieee80211_bss_info_change_notify(sdata, changed);
1543 mutex_unlock(&sdata->u.mgd.mtx); 1547 mutex_unlock(&sdata->u.mgd.mtx);