aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-05 11:48:40 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-11 12:45:00 -0500
commitef429dadf33feeb150098dbe84ccaa877e3261f6 (patch)
tree221694dde4f30fa8f71182a427d34dd709b2821a /net/mac80211/mlme.c
parent8cef2c9df88fdd13f518e6607de9d664b31f26cc (diff)
mac80211: introduce beacon-only timing data
In order to be able to predict the next DTIM TBTT in the driver, add the ability to use timing data from beacons only with the new hardware flag IEEE80211_HW_TIMING_BEACON_ONLY and the BSS info value sync_dtim_count which is only valid if the timing data came from a beacon. The data can only come from a beacon, and if no beacon was received before association it is updated later together with the DTIM count notification. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 51eca5a0cdaa..a29d09cb834c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2567,6 +2567,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2567 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); 2567 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2568 ifmgd->assoc_data->have_beacon = true; 2568 ifmgd->assoc_data->have_beacon = true;
2569 ifmgd->assoc_data->need_beacon = false; 2569 ifmgd->assoc_data->need_beacon = false;
2570 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
2571 sdata->vif.bss_conf.sync_tsf =
2572 le64_to_cpu(mgmt->u.beacon.timestamp);
2573 sdata->vif.bss_conf.sync_device_ts =
2574 rx_status->device_timestamp;
2575 if (elems.tim)
2576 sdata->vif.bss_conf.sync_dtim_count =
2577 elems.tim->dtim_count;
2578 else
2579 sdata->vif.bss_conf.sync_dtim_count = 0;
2580 }
2570 /* continue assoc process */ 2581 /* continue assoc process */
2571 ifmgd->assoc_data->timeout = jiffies; 2582 ifmgd->assoc_data->timeout = jiffies;
2572 run_again(ifmgd, ifmgd->assoc_data->timeout); 2583 run_again(ifmgd, ifmgd->assoc_data->timeout);
@@ -2725,7 +2736,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2725 2736
2726 /* 2737 /*
2727 * If we haven't had a beacon before, tell the driver about the 2738 * If we haven't had a beacon before, tell the driver about the
2728 * DTIM period now. 2739 * DTIM period (and beacon timing if desired) now.
2729 */ 2740 */
2730 if (!bss_conf->dtim_period) { 2741 if (!bss_conf->dtim_period) {
2731 /* a few bogus AP send dtim_period = 0 or no TIM IE */ 2742 /* a few bogus AP send dtim_period = 0 or no TIM IE */
@@ -2733,6 +2744,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2733 bss_conf->dtim_period = elems.tim->dtim_period ?: 1; 2744 bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
2734 else 2745 else
2735 bss_conf->dtim_period = 1; 2746 bss_conf->dtim_period = 1;
2747
2748 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
2749 sdata->vif.bss_conf.sync_tsf =
2750 le64_to_cpu(mgmt->u.beacon.timestamp);
2751 sdata->vif.bss_conf.sync_device_ts =
2752 rx_status->device_timestamp;
2753 if (elems.tim)
2754 sdata->vif.bss_conf.sync_dtim_count =
2755 elems.tim->dtim_count;
2756 else
2757 sdata->vif.bss_conf.sync_dtim_count = 0;
2758 }
2759
2736 changed |= BSS_CHANGED_DTIM_PERIOD; 2760 changed |= BSS_CHANGED_DTIM_PERIOD;
2737 } 2761 }
2738 2762
@@ -3712,10 +3736,33 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3712 /* set timing information */ 3736 /* set timing information */
3713 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; 3737 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
3714 rcu_read_lock(); 3738 rcu_read_lock();
3715 ies = rcu_dereference(cbss->ies); 3739 ies = rcu_dereference(cbss->beacon_ies);
3716 sdata->vif.bss_conf.sync_tsf = ies->tsf; 3740 if (ies) {
3741 const u8 *tim_ie;
3742
3743 sdata->vif.bss_conf.sync_tsf = ies->tsf;
3744 sdata->vif.bss_conf.sync_device_ts =
3745 bss->device_ts_beacon;
3746 tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
3747 ies->data, ies->len);
3748 if (tim_ie && tim_ie[1] >= 2)
3749 sdata->vif.bss_conf.sync_dtim_count = tim_ie[2];
3750 else
3751 sdata->vif.bss_conf.sync_dtim_count = 0;
3752 } else if (!(local->hw.flags &
3753 IEEE80211_HW_TIMING_BEACON_ONLY)) {
3754 ies = rcu_dereference(cbss->proberesp_ies);
3755 /* must be non-NULL since beacon IEs were NULL */
3756 sdata->vif.bss_conf.sync_tsf = ies->tsf;
3757 sdata->vif.bss_conf.sync_device_ts =
3758 bss->device_ts_presp;
3759 sdata->vif.bss_conf.sync_dtim_count = 0;
3760 } else {
3761 sdata->vif.bss_conf.sync_tsf = 0;
3762 sdata->vif.bss_conf.sync_device_ts = 0;
3763 sdata->vif.bss_conf.sync_dtim_count = 0;
3764 }
3717 rcu_read_unlock(); 3765 rcu_read_unlock();
3718 sdata->vif.bss_conf.sync_device_ts = bss->device_ts;
3719 3766
3720 /* tell driver about BSSID, basic rates and timing */ 3767 /* tell driver about BSSID, basic rates and timing */
3721 ieee80211_bss_info_change_notify(sdata, 3768 ieee80211_bss_info_change_notify(sdata,
@@ -4041,13 +4088,23 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4041 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, 4088 const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
4042 beacon_ies->data, 4089 beacon_ies->data,
4043 beacon_ies->len); 4090 beacon_ies->len);
4091 u8 dtim_count = 0;
4092
4044 if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { 4093 if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
4045 const struct ieee80211_tim_ie *tim; 4094 const struct ieee80211_tim_ie *tim;
4046 tim = (void *)(tim_ie + 2); 4095 tim = (void *)(tim_ie + 2);
4047 ifmgd->dtim_period = tim->dtim_period; 4096 ifmgd->dtim_period = tim->dtim_period;
4097 dtim_count = tim->dtim_count;
4048 } 4098 }
4049 assoc_data->have_beacon = true; 4099 assoc_data->have_beacon = true;
4050 assoc_data->timeout = jiffies; 4100 assoc_data->timeout = jiffies;
4101
4102 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
4103 sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf;
4104 sdata->vif.bss_conf.sync_device_ts =
4105 bss->device_ts_beacon;
4106 sdata->vif.bss_conf.sync_dtim_count = dtim_count;
4107 }
4051 } else { 4108 } else {
4052 assoc_data->timeout = jiffies; 4109 assoc_data->timeout = jiffies;
4053 } 4110 }