|
@@ -153,6 +153,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
|
|
|
bf->bf_mpdu = skb;
|
|
|
if (skb == NULL)
|
|
|
return NULL;
|
|
|
+ ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
|
|
|
+ avp->tsf_adjust;
|
|
|
|
|
|
info = IEEE80211_SKB_CB(skb);
|
|
|
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
|
@@ -253,7 +255,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
|
|
|
{
|
|
|
struct ath_softc *sc = aphy->sc;
|
|
|
struct ath_vif *avp;
|
|
|
- struct ieee80211_hdr *hdr;
|
|
|
struct ath_buf *bf;
|
|
|
struct sk_buff *skb;
|
|
|
__le64 tstamp;
|
|
@@ -316,42 +317,33 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
|
|
|
|
|
|
tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
|
|
|
sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
|
|
|
-
|
|
|
- /*
|
|
|
- * Calculate a TSF adjustment factor required for
|
|
|
- * staggered beacons. Note that we assume the format
|
|
|
- * of the beacon frame leaves the tstamp field immediately
|
|
|
- * following the header.
|
|
|
- */
|
|
|
+ /* Calculate a TSF adjustment factor required for staggered beacons. */
|
|
|
if (avp->av_bslot > 0) {
|
|
|
u64 tsfadjust;
|
|
|
- __le64 val;
|
|
|
int intval;
|
|
|
|
|
|
intval = sc->hw->conf.beacon_int ?
|
|
|
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
|
|
|
|
|
|
/*
|
|
|
- * The beacon interval is in TU's; the TSF in usecs.
|
|
|
- * We figure out how many TU's to add to align the
|
|
|
- * timestamp then convert to TSF units and handle
|
|
|
- * byte swapping before writing it in the frame.
|
|
|
- * The hardware will then add this each time a beacon
|
|
|
- * frame is sent. Note that we align vif's 1..N
|
|
|
- * and leave vif 0 untouched. This means vap 0
|
|
|
- * has a timestamp in one beacon interval while the
|
|
|
- * others get a timestamp aligned to the next interval.
|
|
|
+ * Calculate the TSF offset for this beacon slot, i.e., the
|
|
|
+ * number of usecs that need to be added to the timestamp field
|
|
|
+ * in Beacon and Probe Response frames. Beacon slot 0 is
|
|
|
+ * processed at the correct offset, so it does not require TSF
|
|
|
+ * adjustment. Other slots are adjusted to get the timestamp
|
|
|
+ * close to the TBTT for the BSS.
|
|
|
*/
|
|
|
- tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF;
|
|
|
- val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */
|
|
|
+ tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
|
|
|
+ avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
|
|
|
|
|
|
DPRINTF(sc, ATH_DBG_BEACON,
|
|
|
"stagger beacons, bslot %d intval %u tsfadjust %llu\n",
|
|
|
avp->av_bslot, intval, (unsigned long long)tsfadjust);
|
|
|
|
|
|
- hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
- memcpy(&hdr[1], &val, sizeof(val));
|
|
|
- }
|
|
|
+ ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
|
|
|
+ avp->tsf_adjust;
|
|
|
+ } else
|
|
|
+ avp->tsf_adjust = cpu_to_le64(0);
|
|
|
|
|
|
bf->bf_mpdu = skb;
|
|
|
bf->bf_buf_addr = bf->bf_dmacontext =
|
|
@@ -447,8 +439,16 @@ void ath_beacon_tasklet(unsigned long data)
|
|
|
tsf = ath9k_hw_gettsf64(ah);
|
|
|
tsftu = TSF_TO_TU(tsf>>32, tsf);
|
|
|
slot = ((tsftu % intval) * ATH_BCBUF) / intval;
|
|
|
- vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF];
|
|
|
- aphy = sc->beacon.bslot_aphy[(slot + 1) % ATH_BCBUF];
|
|
|
+ /*
|
|
|
+ * Reverse the slot order to get slot 0 on the TBTT offset that does
|
|
|
+ * not require TSF adjustment and other slots adding
|
|
|
+ * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
|
|
|
+ * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
|
|
|
+ * and slot 0 is at correct offset to TBTT.
|
|
|
+ */
|
|
|
+ slot = ATH_BCBUF - slot - 1;
|
|
|
+ vif = sc->beacon.bslot[slot];
|
|
|
+ aphy = sc->beacon.bslot_aphy[slot];
|
|
|
|
|
|
DPRINTF(sc, ATH_DBG_BEACON,
|
|
|
"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
|