aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/beacon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath9k/beacon.c')
-rw-r--r--drivers/net/wireless/ath9k/beacon.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 039c78136c50..ec995730632d 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008 Atheros Communications Inc. 2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 * 3 *
4 * Permission to use, copy, modify, and/or distribute this software for any 4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 5 * purpose with or without fee is hereby granted, provided that the above
@@ -70,7 +70,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
70 ds = bf->bf_desc; 70 ds = bf->bf_desc;
71 flags = ATH9K_TXDESC_NOACK; 71 flags = ATH9K_TXDESC_NOACK;
72 72
73 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC && 73 if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
74 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
74 (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { 75 (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
75 ds->ds_link = bf->bf_daddr; /* self-linked */ 76 ds->ds_link = bf->bf_daddr; /* self-linked */
76 flags |= ATH9K_TXDESC_VEOL; 77 flags |= ATH9K_TXDESC_VEOL;
@@ -153,6 +154,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
153 bf->bf_mpdu = skb; 154 bf->bf_mpdu = skb;
154 if (skb == NULL) 155 if (skb == NULL)
155 return NULL; 156 return NULL;
157 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
158 avp->tsf_adjust;
156 159
157 info = IEEE80211_SKB_CB(skb); 160 info = IEEE80211_SKB_CB(skb);
158 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 161 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
@@ -253,7 +256,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
253{ 256{
254 struct ath_softc *sc = aphy->sc; 257 struct ath_softc *sc = aphy->sc;
255 struct ath_vif *avp; 258 struct ath_vif *avp;
256 struct ieee80211_hdr *hdr;
257 struct ath_buf *bf; 259 struct ath_buf *bf;
258 struct sk_buff *skb; 260 struct sk_buff *skb;
259 __le64 tstamp; 261 __le64 tstamp;
@@ -316,42 +318,33 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
316 318
317 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; 319 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
318 sc->beacon.bc_tstamp = le64_to_cpu(tstamp); 320 sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
319 321 /* Calculate a TSF adjustment factor required for staggered beacons. */
320 /*
321 * Calculate a TSF adjustment factor required for
322 * staggered beacons. Note that we assume the format
323 * of the beacon frame leaves the tstamp field immediately
324 * following the header.
325 */
326 if (avp->av_bslot > 0) { 322 if (avp->av_bslot > 0) {
327 u64 tsfadjust; 323 u64 tsfadjust;
328 __le64 val;
329 int intval; 324 int intval;
330 325
331 intval = sc->hw->conf.beacon_int ? 326 intval = sc->hw->conf.beacon_int ?
332 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; 327 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
333 328
334 /* 329 /*
335 * The beacon interval is in TU's; the TSF in usecs. 330 * Calculate the TSF offset for this beacon slot, i.e., the
336 * We figure out how many TU's to add to align the 331 * number of usecs that need to be added to the timestamp field
337 * timestamp then convert to TSF units and handle 332 * in Beacon and Probe Response frames. Beacon slot 0 is
338 * byte swapping before writing it in the frame. 333 * processed at the correct offset, so it does not require TSF
339 * The hardware will then add this each time a beacon 334 * adjustment. Other slots are adjusted to get the timestamp
340 * frame is sent. Note that we align vif's 1..N 335 * close to the TBTT for the BSS.
341 * and leave vif 0 untouched. This means vap 0
342 * has a timestamp in one beacon interval while the
343 * others get a timestamp aligned to the next interval.
344 */ 336 */
345 tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; 337 tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
346 val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ 338 avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
347 339
348 DPRINTF(sc, ATH_DBG_BEACON, 340 DPRINTF(sc, ATH_DBG_BEACON,
349 "stagger beacons, bslot %d intval %u tsfadjust %llu\n", 341 "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
350 avp->av_bslot, intval, (unsigned long long)tsfadjust); 342 avp->av_bslot, intval, (unsigned long long)tsfadjust);
351 343
352 hdr = (struct ieee80211_hdr *)skb->data; 344 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
353 memcpy(&hdr[1], &val, sizeof(val)); 345 avp->tsf_adjust;
354 } 346 } else
347 avp->tsf_adjust = cpu_to_le64(0);
355 348
356 bf->bf_mpdu = skb; 349 bf->bf_mpdu = skb;
357 bf->bf_buf_addr = bf->bf_dmacontext = 350 bf->bf_buf_addr = bf->bf_dmacontext =
@@ -447,8 +440,16 @@ void ath_beacon_tasklet(unsigned long data)
447 tsf = ath9k_hw_gettsf64(ah); 440 tsf = ath9k_hw_gettsf64(ah);
448 tsftu = TSF_TO_TU(tsf>>32, tsf); 441 tsftu = TSF_TO_TU(tsf>>32, tsf);
449 slot = ((tsftu % intval) * ATH_BCBUF) / intval; 442 slot = ((tsftu % intval) * ATH_BCBUF) / intval;
450 vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; 443 /*
451 aphy = sc->beacon.bslot_aphy[(slot + 1) % ATH_BCBUF]; 444 * Reverse the slot order to get slot 0 on the TBTT offset that does
445 * not require TSF adjustment and other slots adding
446 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
447 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
448 * and slot 0 is at correct offset to TBTT.
449 */
450 slot = ATH_BCBUF - slot - 1;
451 vif = sc->beacon.bslot[slot];
452 aphy = sc->beacon.bslot_aphy[slot];
452 453
453 DPRINTF(sc, ATH_DBG_BEACON, 454 DPRINTF(sc, ATH_DBG_BEACON,
454 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", 455 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
@@ -728,6 +729,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
728 ath_beacon_config_ap(sc, &conf, avp); 729 ath_beacon_config_ap(sc, &conf, avp);
729 break; 730 break;
730 case NL80211_IFTYPE_ADHOC: 731 case NL80211_IFTYPE_ADHOC:
732 case NL80211_IFTYPE_MESH_POINT:
731 ath_beacon_config_adhoc(sc, &conf, avp, vif); 733 ath_beacon_config_adhoc(sc, &conf, avp, vif);
732 break; 734 break;
733 case NL80211_IFTYPE_STATION: 735 case NL80211_IFTYPE_STATION: