aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c75
1 files changed, 54 insertions, 21 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7753a9ca98a6..a3552929a21d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1074,12 +1074,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
1074 if (beaconint_us > latency) { 1074 if (beaconint_us > latency) {
1075 local->ps_sdata = NULL; 1075 local->ps_sdata = NULL;
1076 } else { 1076 } else {
1077 struct ieee80211_bss *bss;
1078 int maxslp = 1; 1077 int maxslp = 1;
1079 u8 dtimper; 1078 u8 dtimper = found->u.mgd.dtim_period;
1080
1081 bss = (void *)found->u.mgd.associated->priv;
1082 dtimper = bss->dtim_period;
1083 1079
1084 /* If the TIM IE is invalid, pretend the value is 1 */ 1080 /* If the TIM IE is invalid, pretend the value is 1 */
1085 if (!dtimper) 1081 if (!dtimper)
@@ -1410,10 +1406,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1410 1406
1411 ieee80211_led_assoc(local, 1); 1407 ieee80211_led_assoc(local, 1);
1412 1408
1413 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) 1409 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
1414 bss_conf->dtim_period = bss->dtim_period; 1410 /*
1415 else 1411 * If the AP is buggy we may get here with no DTIM period
1412 * known, so assume it's 1 which is the only safe assumption
1413 * in that case, although if the TIM IE is broken powersave
1414 * probably just won't work at all.
1415 */
1416 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
1417 } else {
1416 bss_conf->dtim_period = 0; 1418 bss_conf->dtim_period = 0;
1419 }
1417 1420
1418 bss_conf->assoc = 1; 1421 bss_conf->assoc = 1;
1419 1422
@@ -1562,6 +1565,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1562 1565
1563 sdata->u.mgd.timers_running = 0; 1566 sdata->u.mgd.timers_running = 0;
1564 1567
1568 sdata->vif.bss_conf.dtim_period = 0;
1569
1565 ifmgd->flags = 0; 1570 ifmgd->flags = 0;
1566 ieee80211_vif_release_channel(sdata); 1571 ieee80211_vif_release_channel(sdata);
1567} 1572}
@@ -2373,11 +2378,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2373 struct ieee80211_channel *channel; 2378 struct ieee80211_channel *channel;
2374 bool need_ps = false; 2379 bool need_ps = false;
2375 2380
2376 if (sdata->u.mgd.associated && 2381 if ((sdata->u.mgd.associated &&
2377 ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) { 2382 ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
2378 bss = (void *)sdata->u.mgd.associated->priv; 2383 (sdata->u.mgd.assoc_data &&
2384 ether_addr_equal(mgmt->bssid,
2385 sdata->u.mgd.assoc_data->bss->bssid))) {
2379 /* not previously set so we may need to recalc */ 2386 /* not previously set so we may need to recalc */
2380 need_ps = !bss->dtim_period; 2387 need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period;
2388
2389 if (elems->tim && !elems->parse_error) {
2390 struct ieee80211_tim_ie *tim_ie = elems->tim;
2391 sdata->u.mgd.dtim_period = tim_ie->dtim_period;
2392 }
2381 } 2393 }
2382 2394
2383 if (elems->ds_params && elems->ds_params_len == 1) 2395 if (elems->ds_params && elems->ds_params_len == 1)
@@ -3896,20 +3908,41 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3896 /* kick off associate process */ 3908 /* kick off associate process */
3897 3909
3898 ifmgd->assoc_data = assoc_data; 3910 ifmgd->assoc_data = assoc_data;
3911 ifmgd->dtim_period = 0;
3899 3912
3900 err = ieee80211_prep_connection(sdata, req->bss, true); 3913 err = ieee80211_prep_connection(sdata, req->bss, true);
3901 if (err) 3914 if (err)
3902 goto err_clear; 3915 goto err_clear;
3903 3916
3904 if (!bss->dtim_period && 3917 if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
3905 sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { 3918 const struct cfg80211_bss_ies *beacon_ies;
3906 /* 3919
3907 * Wait up to one beacon interval ... 3920 rcu_read_lock();
3908 * should this be more if we miss one? 3921 beacon_ies = rcu_dereference(req->bss->beacon_ies);
3909 */ 3922 if (!beacon_ies) {
3910 sdata_info(sdata, "waiting for beacon from %pM\n", 3923 /*
3911 ifmgd->bssid); 3924 * Wait up to one beacon interval ...
3912 assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); 3925 * should this be more if we miss one?
3926 */
3927 sdata_info(sdata, "waiting for beacon from %pM\n",
3928 ifmgd->bssid);
3929 assoc_data->timeout =
3930 TU_TO_EXP_TIME(req->bss->beacon_interval);
3931 } else {
3932 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
3933 beacon_ies->data,
3934 beacon_ies->len);
3935 if (tim_ie && tim_ie[1] >=
3936 sizeof(struct ieee80211_tim_ie)) {
3937 const struct ieee80211_tim_ie *tim;
3938 tim = (void *)(tim_ie + 2);
3939 ifmgd->dtim_period = tim->dtim_period;
3940 }
3941 assoc_data->have_beacon = true;
3942 assoc_data->sent_assoc = false;
3943 assoc_data->timeout = jiffies;
3944 }
3945 rcu_read_unlock();
3913 } else { 3946 } else {
3914 assoc_data->have_beacon = true; 3947 assoc_data->have_beacon = true;
3915 assoc_data->sent_assoc = false; 3948 assoc_data->sent_assoc = false;