aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/net/mac80211.h14
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c65
-rw-r--r--net/mac80211/scan.c5
-rw-r--r--net/mac80211/trace.h2
5 files changed, 81 insertions, 7 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 46e08ba92b97..b9e02460d3d7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -277,9 +277,16 @@ enum ieee80211_rssi_event {
277 * valid in station mode only if after the driver was notified 277 * valid in station mode only if after the driver was notified
278 * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then. 278 * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then.
279 * @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
280 * as it may have been received during scanning long ago) 280 * as it may have been received during scanning long ago). If the
281 * HW flag %IEEE80211_HW_TIMING_BEACON_ONLY is set, then this can
282 * only come from a beacon, but might not become valid until after
283 * association when a beacon is received (which is notified with the
284 * %BSS_CHANGED_DTIM flag.)
281 * @sync_device_ts: the device timestamp corresponding to the sync_tsf, 285 * @sync_device_ts: the device timestamp corresponding to the sync_tsf,
282 * the driver/device can use this to calculate synchronisation 286 * the driver/device can use this to calculate synchronisation
287 * (see @sync_tsf)
288 * @sync_dtim_count: Only valid when %IEEE80211_HW_TIMING_BEACON_ONLY
289 * is requested, see @sync_tsf/@sync_device_ts.
283 * @beacon_int: beacon interval 290 * @beacon_int: beacon interval
284 * @assoc_capability: capabilities taken from assoc resp 291 * @assoc_capability: capabilities taken from assoc resp
285 * @basic_rates: bitmap of basic rates, each bit stands for an 292 * @basic_rates: bitmap of basic rates, each bit stands for an
@@ -331,6 +338,7 @@ struct ieee80211_bss_conf {
331 u16 assoc_capability; 338 u16 assoc_capability;
332 u64 sync_tsf; 339 u64 sync_tsf;
333 u32 sync_device_ts; 340 u32 sync_device_ts;
341 u8 sync_dtim_count;
334 u32 basic_rates; 342 u32 basic_rates;
335 int mcast_rate[IEEE80211_NUM_BANDS]; 343 int mcast_rate[IEEE80211_NUM_BANDS];
336 u16 ht_operation_mode; 344 u16 ht_operation_mode;
@@ -1371,6 +1379,9 @@ struct ieee80211_tx_control {
1371 * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any 1379 * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
1372 * P2P Interface. This will be honoured even if more than one interface 1380 * P2P Interface. This will be honoured even if more than one interface
1373 * is supported. 1381 * is supported.
1382 *
1383 * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames
1384 * only, to allow getting TBTT of a DTIM beacon.
1374 */ 1385 */
1375enum ieee80211_hw_flags { 1386enum ieee80211_hw_flags {
1376 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, 1387 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -1399,6 +1410,7 @@ enum ieee80211_hw_flags {
1399 IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, 1410 IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
1400 IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, 1411 IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24,
1401 IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, 1412 IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25,
1413 IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26,
1402}; 1414};
1403 1415
1404/** 1416/**
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8e884fcbe79b..d794856933f2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -86,7 +86,7 @@ struct ieee80211_fragment_entry {
86 86
87 87
88struct ieee80211_bss { 88struct ieee80211_bss {
89 u32 device_ts; 89 u32 device_ts_beacon, device_ts_presp;
90 90
91 bool wmm_used; 91 bool wmm_used;
92 bool uapsd_supported; 92 bool uapsd_supported;
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 }
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 400153f7f21f..edd47d9acb99 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -80,7 +80,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
80 80
81 bss = (void *)cbss->priv; 81 bss = (void *)cbss->priv;
82 82
83 bss->device_ts = rx_status->device_timestamp; 83 if (beacon)
84 bss->device_ts_beacon = rx_status->device_timestamp;
85 else
86 bss->device_ts_presp = rx_status->device_timestamp;
84 87
85 if (elems->parse_error) { 88 if (elems->parse_error) {
86 if (beacon) 89 if (beacon)
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index a2ca72ce3380..0bdd7aeb8958 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -340,6 +340,7 @@ TRACE_EVENT(drv_bss_info_changed,
340 __field(u16, assoc_cap) 340 __field(u16, assoc_cap)
341 __field(u64, sync_tsf) 341 __field(u64, sync_tsf)
342 __field(u32, sync_device_ts) 342 __field(u32, sync_device_ts)
343 __field(u8, sync_dtim_count)
343 __field(u32, basic_rates) 344 __field(u32, basic_rates)
344 __array(int, mcast_rate, IEEE80211_NUM_BANDS) 345 __array(int, mcast_rate, IEEE80211_NUM_BANDS)
345 __field(u16, ht_operation_mode) 346 __field(u16, ht_operation_mode)
@@ -379,6 +380,7 @@ TRACE_EVENT(drv_bss_info_changed,
379 __entry->assoc_cap = info->assoc_capability; 380 __entry->assoc_cap = info->assoc_capability;
380 __entry->sync_tsf = info->sync_tsf; 381 __entry->sync_tsf = info->sync_tsf;
381 __entry->sync_device_ts = info->sync_device_ts; 382 __entry->sync_device_ts = info->sync_device_ts;
383 __entry->sync_dtim_count = info->sync_dtim_count;
382 __entry->basic_rates = info->basic_rates; 384 __entry->basic_rates = info->basic_rates;
383 memcpy(__entry->mcast_rate, info->mcast_rate, 385 memcpy(__entry->mcast_rate, info->mcast_rate,
384 sizeof(__entry->mcast_rate)); 386 sizeof(__entry->mcast_rate));