diff options
author | Thomas Pedersen <thomas@cozybit.com> | 2012-11-13 13:46:27 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-11-13 15:43:55 -0500 |
commit | f4bda337bbb6e245e2a07f344990adeb6a70ff35 (patch) | |
tree | 6ccf2bc38fb67098df931ce55eb0905959813864 /net/mac80211 | |
parent | 2a91c9f781de209d420d751e43eb43ffe6934803 (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.c | 29 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 11 | ||||
-rw-r--r-- | net/mac80211/mesh_sync.c | 44 | ||||
-rw-r--r-- | net/mac80211/rx.c | 14 | ||||
-rw-r--r-- | net/mac80211/util.c | 51 |
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 | ||
1262 | static inline bool | ||
1263 | ieee80211_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 | ||
1270 | u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | ||
1271 | struct ieee80211_rx_status *status, | ||
1272 | unsigned int mpdu_len, | ||
1273 | unsigned int mpdu_offset); | ||
1263 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); | 1274 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); |
1264 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 1275 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
1265 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 1276 | void 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 | */ | ||
2028 | u64 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 | } | ||