|
@@ -284,6 +284,7 @@ static void wlc_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
|
|
|
static void wlc_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
|
|
|
static u16 wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate,
|
|
|
u8 preamble_type, uint next_frag_len);
|
|
|
+static u64 wlc_recover_tsf64(struct wlc_info *wlc, struct wlc_d11rxhdr *rxh);
|
|
|
static void wlc_recvctl(struct wlc_info *wlc,
|
|
|
d11rxhdr_t *rxh, struct sk_buff *p);
|
|
|
static uint wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t rate,
|
|
@@ -6474,25 +6475,56 @@ void wlc_bcn_li_upd(struct wlc_info *wlc)
|
|
|
(wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * recover 64bit TSF value from the 16bit TSF value in the rx header
|
|
|
+ * given the assumption that the TSF passed in header is within 65ms
|
|
|
+ * of the current tsf.
|
|
|
+ *
|
|
|
+ * 6 5 4 4 3 2 1
|
|
|
+ * 3.......6.......8.......0.......2.......4.......6.......8......0
|
|
|
+ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
|
|
|
+ *
|
|
|
+ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
|
|
|
+ * tsf_l is filled in by wlc_bmac_recv, which is done earlier in the
|
|
|
+ * receive call sequence after rx interrupt. Only the higher 16 bits
|
|
|
+ * are used. Finally, the tsf_h is read from the tsf register.
|
|
|
+ */
|
|
|
+static u64 wlc_recover_tsf64(struct wlc_info *wlc, struct wlc_d11rxhdr *rxh)
|
|
|
+{
|
|
|
+ u32 tsf_h, tsf_l;
|
|
|
+ u16 rx_tsf_0_15, rx_tsf_16_31;
|
|
|
+
|
|
|
+ wlc_bmac_read_tsf(wlc->hw, &tsf_l, &tsf_h);
|
|
|
+
|
|
|
+ rx_tsf_16_31 = (u16)(tsf_l >> 16);
|
|
|
+ rx_tsf_0_15 = rxh->rxhdr.RxTSFTime;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * a greater tsf time indicates the low 16 bits of
|
|
|
+ * tsf_l wrapped, so decrement the high 16 bits.
|
|
|
+ */
|
|
|
+ if ((u16)tsf_l < rx_tsf_0_15) {
|
|
|
+ rx_tsf_16_31 -= 1;
|
|
|
+ if (rx_tsf_16_31 == 0xffff)
|
|
|
+ tsf_h -= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
prep_mac80211_status(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p,
|
|
|
struct ieee80211_rx_status *rx_status)
|
|
|
{
|
|
|
- u32 tsf_l, tsf_h;
|
|
|
wlc_d11rxhdr_t *wlc_rxh = (wlc_d11rxhdr_t *) rxh;
|
|
|
int preamble;
|
|
|
int channel;
|
|
|
ratespec_t rspec;
|
|
|
unsigned char *plcp;
|
|
|
|
|
|
-#if 0
|
|
|
- /* Clearly, this is bogus -- reading the TSF now is wrong */
|
|
|
- wlc_read_tsf(wlc, &tsf_l, &tsf_h); /* mactime */
|
|
|
- rx_status->mactime = tsf_h;
|
|
|
- rx_status->mactime <<= 32;
|
|
|
- rx_status->mactime |= tsf_l;
|
|
|
- rx_status->flag |= RX_FLAG_MACTIME_MPDU; /* clearly wrong */
|
|
|
-#endif
|
|
|
+ /* fill in TSF and flag its presence */
|
|
|
+ rx_status->mactime = wlc_recover_tsf64(wlc, wlc_rxh);
|
|
|
+ rx_status->flag |= RX_FLAG_MACTIME_MPDU;
|
|
|
|
|
|
channel = WLC_CHAN_CHANNEL(rxh->RxChan);
|
|
|
|