summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2012-12-12 03:12:24 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-01-31 08:05:38 -0500
commitc65dd1477b6fe5971489dd8b6e28a07ec277fdd6 (patch)
tree01f740a3fa02bc957b22575fcd1bb486b0af6e43 /net/mac80211/mlme.c
parentfdcb786930777231c81f487ab2526d33971a3438 (diff)
mac80211: inform the driver about update of dtim_period
Currently, when the driver requires the DTIM period, mac80211 will wait to hear a beacon before association. This behavior is suboptimal since some drivers may be able to deal with knowing the DTIM period after the association, if they get it at all. To address this, notify the drivers with bss_info_changed with the new BSS_CHANGED_DTIM_PERIOD flag when the DTIM becomes known. This might be when changing to associated, or later when the entire association was done with only probe response information. Rename the hardware flag for the current behaviour to IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC to more accurately reflect its behaviour. IEEE80211_HW_NEED_DTIM_PERIOD is no longer accurate as all drivers get the DTIM period now, just not before association. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c74
1 files changed, 44 insertions, 30 deletions
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) {