diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2010-01-26 08:19:52 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-26 11:53:21 -0500 |
commit | 56007a028c51cbf800a6c969d6f6431d23443b99 (patch) | |
tree | 8bc0280467824ed3b5f95810444b1f8e1ebc2750 /net/mac80211/mlme.c | |
parent | c21dbf9214bce129f92e1af05552553ff0e318ed (diff) |
mac80211: wait for beacon before enabling powersave
Because DTIM information is required for powersave
but is only conveyed in beacons, wait for a beacon
before enabling powersave, and change the way the
information is conveyed to the driver accordingly.
mwl8k doesn't currently seem to implement PS but
requires the DTIM period in a different way; after
talking to Lennert we agreed to just have mwl8k do
the parsing itself in the finalize_join work.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1e1d16c55ee5..86c6ad1b058d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -484,6 +484,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
484 | 484 | ||
485 | if (count == 1 && found->u.mgd.powersave && | 485 | if (count == 1 && found->u.mgd.powersave && |
486 | found->u.mgd.associated && | 486 | found->u.mgd.associated && |
487 | found->u.mgd.associated->beacon_ies && | ||
487 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | | 488 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | |
488 | IEEE80211_STA_CONNECTION_POLL))) { | 489 | IEEE80211_STA_CONNECTION_POLL))) { |
489 | s32 beaconint_us; | 490 | s32 beaconint_us; |
@@ -497,14 +498,22 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
497 | if (beaconint_us > latency) { | 498 | if (beaconint_us > latency) { |
498 | local->ps_sdata = NULL; | 499 | local->ps_sdata = NULL; |
499 | } else { | 500 | } else { |
500 | u8 dtimper = found->vif.bss_conf.dtim_period; | 501 | struct ieee80211_bss *bss; |
501 | int maxslp = 1; | 502 | int maxslp = 1; |
503 | u8 dtimper; | ||
502 | 504 | ||
503 | if (dtimper > 1) | 505 | bss = (void *)found->u.mgd.associated->priv; |
506 | dtimper = bss->dtim_period; | ||
507 | |||
508 | /* If the TIM IE is invalid, pretend the value is 1 */ | ||
509 | if (!dtimper) | ||
510 | dtimper = 1; | ||
511 | else if (dtimper > 1) | ||
504 | maxslp = min_t(int, dtimper, | 512 | maxslp = min_t(int, dtimper, |
505 | latency / beaconint_us); | 513 | latency / beaconint_us); |
506 | 514 | ||
507 | local->hw.conf.max_sleep_period = maxslp; | 515 | local->hw.conf.max_sleep_period = maxslp; |
516 | local->hw.conf.ps_dtim_period = dtimper; | ||
508 | local->ps_sdata = found; | 517 | local->ps_sdata = found; |
509 | } | 518 | } |
510 | } else { | 519 | } else { |
@@ -702,7 +711,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
702 | /* set timing information */ | 711 | /* set timing information */ |
703 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; | 712 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; |
704 | sdata->vif.bss_conf.timestamp = cbss->tsf; | 713 | sdata->vif.bss_conf.timestamp = cbss->tsf; |
705 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; | ||
706 | 714 | ||
707 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | 715 | bss_info_changed |= BSS_CHANGED_BEACON_INT; |
708 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 716 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
@@ -1168,6 +1176,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1168 | int freq; | 1176 | int freq; |
1169 | struct ieee80211_bss *bss; | 1177 | struct ieee80211_bss *bss; |
1170 | struct ieee80211_channel *channel; | 1178 | struct ieee80211_channel *channel; |
1179 | bool need_ps = false; | ||
1180 | |||
1181 | if (sdata->u.mgd.associated) { | ||
1182 | bss = (void *)sdata->u.mgd.associated->priv; | ||
1183 | /* not previously set so we may need to recalc */ | ||
1184 | need_ps = !bss->dtim_period; | ||
1185 | } | ||
1171 | 1186 | ||
1172 | if (elems->ds_params && elems->ds_params_len == 1) | 1187 | if (elems->ds_params && elems->ds_params_len == 1) |
1173 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1188 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); |
@@ -1187,6 +1202,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1187 | if (!sdata->u.mgd.associated) | 1202 | if (!sdata->u.mgd.associated) |
1188 | return; | 1203 | return; |
1189 | 1204 | ||
1205 | if (need_ps) { | ||
1206 | mutex_lock(&local->iflist_mtx); | ||
1207 | ieee80211_recalc_ps(local, -1); | ||
1208 | mutex_unlock(&local->iflist_mtx); | ||
1209 | } | ||
1210 | |||
1190 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && | 1211 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && |
1191 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, | 1212 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, |
1192 | ETH_ALEN) == 0)) { | 1213 | ETH_ALEN) == 0)) { |