aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2012-11-13 13:46:27 -0500
committerJohannes Berg <johannes.berg@intel.com>2012-11-13 15:43:55 -0500
commitf4bda337bbb6e245e2a07f344990adeb6a70ff35 (patch)
tree6ccf2bc38fb67098df931ce55eb0905959813864 /net/mac80211
parent2a91c9f781de209d420d751e43eb43ffe6934803 (diff)
mac80211: support RX_FLAG_MACTIME_END
Allow drivers to indicate their mactime is at RX completion and adjust for this in mac80211. Also rename the existing RX_FLAG_MACTIME_MPDU to RX_FLAG_MACTIME_START to clarify its intent. Based on similar code by Johannes Berg. Signed-off-by: Thomas Pedersen <thomas@cozybit.com> [fix docs, atheros drivers] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c29
-rw-r--r--net/mac80211/ieee80211_i.h11
-rw-r--r--net/mac80211/mesh_sync.c44
-rw-r--r--net/mac80211/rx.c14
-rw-r--r--net/mac80211/util.c51
5 files changed, 85 insertions, 64 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index c7386b2b767e..cc11558d8c1a 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -543,30 +543,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
543 if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) 543 if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid))
544 goto put_bss; 544 goto put_bss;
545 545
546 if (rx_status->flag & RX_FLAG_MACTIME_MPDU) { 546 if (ieee80211_have_rx_timestamp(rx_status)) {
547 /* 547 /* time when timestamp field was received */
548 * For correct IBSS merging we need mactime; since mactime is 548 rx_timestamp =
549 * defined as the time the first data symbol of the frame hits 549 ieee80211_calculate_rx_timestamp(local, rx_status,
550 * the PHY, and the timestamp of the beacon is defined as "the 550 len + FCS_LEN, 24);
551 * time that the data symbol containing the first bit of the
552 * timestamp is transmitted to the PHY plus the transmitting
553 * STA's delays through its local PHY from the MAC-PHY
554 * interface to its interface with the WM" (802.11 11.1.2)
555 * - equals the time this bit arrives at the receiver - we have
556 * to take into account the offset between the two.
557 *
558 * E.g. at 1 MBit that means mactime is 192 usec earlier
559 * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
560 */
561 int rate;
562
563 if (rx_status->flag & RX_FLAG_HT)
564 rate = 65; /* TODO: HT rates */
565 else
566 rate = local->hw.wiphy->bands[band]->
567 bitrates[rx_status->rate_idx].bitrate;
568
569 rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
570 } else { 551 } else {
571 /* 552 /*
572 * second best option: get current TSF 553 * second best option: get current TSF
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e1fb97cc9a41..bff82a8e62f3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1259,7 +1259,18 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
1259 is_broadcast_ether_addr(raddr); 1259 is_broadcast_ether_addr(raddr);
1260} 1260}
1261 1261
1262static inline bool
1263ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
1264{
1265 WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START &&
1266 status->flag & RX_FLAG_MACTIME_END);
1267 return status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END);
1268}
1262 1269
1270u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
1271 struct ieee80211_rx_status *status,
1272 unsigned int mpdu_len,
1273 unsigned int mpdu_offset);
1263int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); 1274int ieee80211_hw_config(struct ieee80211_local *local, u32 changed);
1264void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); 1275void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
1265void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 1276void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c
index 407c8705e10d..9c6ea9cfe1b3 100644
--- a/net/mac80211/mesh_sync.c
+++ b/net/mac80211/mesh_sync.c
@@ -116,43 +116,13 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
116 goto no_sync; 116 goto no_sync;
117 } 117 }
118 118
119 if (rx_status->flag & RX_FLAG_MACTIME_MPDU && rx_status->mactime) { 119 if (ieee80211_have_rx_timestamp(rx_status))
120 /* 120 /* time when timestamp field was received */
121 * The mactime is defined as the time the first data symbol 121 t_r = ieee80211_calculate_rx_timestamp(local, rx_status,
122 * of the frame hits the PHY, and the timestamp of the beacon 122 24 + 12 +
123 * is defined as "the time that the data symbol containing the 123 elems->total_len +
124 * first bit of the timestamp is transmitted to the PHY plus 124 FCS_LEN,
125 * the transmitting STA's delays through its local PHY from the 125 24);
126 * MAC-PHY interface to its interface with the WM" (802.11
127 * 11.1.2)
128 *
129 * T_r, in 13.13.2.2.2, is just defined as "the frame reception
130 * time" but we unless we interpret that time to be the same
131 * time of the beacon timestamp, the offset calculation will be
132 * off. Below we adjust t_r to be "the time at which the first
133 * symbol of the timestamp element in the beacon is received".
134 * This correction depends on the rate.
135 *
136 * Based on similar code in ibss.c
137 */
138 int rate;
139
140 if (rx_status->flag & RX_FLAG_HT) {
141 /* TODO:
142 * In principle there could be HT-beacons (Dual Beacon
143 * HT Operation options), but for now ignore them and
144 * just use the primary (i.e. non-HT) beacons for
145 * synchronization.
146 * */
147 goto no_sync;
148 } else
149 rate = local->hw.wiphy->bands[rx_status->band]->
150 bitrates[rx_status->rate_idx].bitrate;
151
152 /* 24 bytes of header * 8 bits/byte *
153 * 10*(100 Kbps)/Mbps / rate (100 Kbps)*/
154 t_r = rx_status->mactime + (24 * 8 * 10 / rate);
155 }
156 126
157 /* Timing offset calculation (see 13.13.2.2.2) */ 127 /* Timing offset calculation (see 13.13.2.2.2) */
158 t_t = le64_to_cpu(mgmt->u.beacon.timestamp); 128 t_t = le64_to_cpu(mgmt->u.beacon.timestamp);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6ad330341b71..e3daee8fdf7a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -81,7 +81,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
81 /* always present fields */ 81 /* always present fields */
82 len = sizeof(struct ieee80211_radiotap_header) + 9; 82 len = sizeof(struct ieee80211_radiotap_header) + 9;
83 83
84 if (status->flag & RX_FLAG_MACTIME_MPDU) 84 if (ieee80211_have_rx_timestamp(status))
85 len += 8; 85 len += 8;
86 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 86 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
87 len += 1; 87 len += 1;
@@ -117,6 +117,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
117 struct ieee80211_radiotap_header *rthdr; 117 struct ieee80211_radiotap_header *rthdr;
118 unsigned char *pos; 118 unsigned char *pos;
119 u16 rx_flags = 0; 119 u16 rx_flags = 0;
120 int mpdulen;
121
122 mpdulen = skb->len;
123 if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
124 mpdulen += FCS_LEN;
120 125
121 rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); 126 rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
122 memset(rthdr, 0, rtap_len); 127 memset(rthdr, 0, rtap_len);
@@ -134,8 +139,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
134 /* the order of the following fields is important */ 139 /* the order of the following fields is important */
135 140
136 /* IEEE80211_RADIOTAP_TSFT */ 141 /* IEEE80211_RADIOTAP_TSFT */
137 if (status->flag & RX_FLAG_MACTIME_MPDU) { 142 if (ieee80211_have_rx_timestamp(status)) {
138 put_unaligned_le64(status->mactime, pos); 143 put_unaligned_le64(
144 ieee80211_calculate_rx_timestamp(local, status,
145 mpdulen, 0),
146 pos);
139 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); 147 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
140 pos += 8; 148 pos += 8;
141 } 149 }
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4e4f58513673..5bad758abfb3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2013,3 +2013,54 @@ u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs)
2013 return 2; 2013 return 2;
2014 return 1; 2014 return 1;
2015} 2015}
2016
2017/**
2018 * ieee80211_calculate_rx_timestamp - calculate timestamp in frame
2019 * @local: mac80211 hw info struct
2020 * @status: RX status
2021 * @mpdu_len: total MPDU length (including FCS)
2022 * @mpdu_offset: offset into MPDU to calculate timestamp at
2023 *
2024 * This function calculates the RX timestamp at the given MPDU offset, taking
2025 * into account what the RX timestamp was. An offset of 0 will just normalize
2026 * the timestamp to TSF at beginning of MPDU reception.
2027 */
2028u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
2029 struct ieee80211_rx_status *status,
2030 unsigned int mpdu_len,
2031 unsigned int mpdu_offset)
2032{
2033 u64 ts = status->mactime;
2034 struct rate_info ri;
2035 u16 rate;
2036
2037 if (WARN_ON(!ieee80211_have_rx_timestamp(status)))
2038 return 0;
2039
2040 memset(&ri, 0, sizeof(ri));
2041
2042 /* Fill cfg80211 rate info */
2043 if (status->flag & RX_FLAG_HT) {
2044 ri.mcs = status->rate_idx;
2045 ri.flags |= RATE_INFO_FLAGS_MCS;
2046 if (status->flag & RX_FLAG_40MHZ)
2047 ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
2048 if (status->flag & RX_FLAG_SHORT_GI)
2049 ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
2050 } else {
2051 struct ieee80211_supported_band *sband;
2052
2053 sband = local->hw.wiphy->bands[status->band];
2054 ri.legacy = sband->bitrates[status->rate_idx].bitrate;
2055 }
2056
2057 rate = cfg80211_calculate_bitrate(&ri);
2058
2059 /* rewind from end of MPDU */
2060 if (status->flag & RX_FLAG_MACTIME_END)
2061 ts -= mpdu_len * 8 * 10 / rate;
2062
2063 ts += mpdu_offset * 8 * 10 / rate;
2064
2065 return ts;
2066}