ath9k: Add support for multiple virtual AP interfaces
authorJouni Malinen <jouni.malinen@atheros.com>
Thu, 12 Mar 2009 19:53:23 +0000 (21:53 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Sat, 28 Mar 2009 00:12:46 +0000 (20:12 -0400)
This patch fixes the TSF offset calculation for staggered Beacon frames
and sets ATH_BCBUF back to the earlier value 4 to enable multi-BSS
configurations of up to four BSSes.

Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath9k/ath9k.h
drivers/net/wireless/ath9k/beacon.c

index b64be8e9a69029ba067b241de1a771f8a2060803..5afd244ea6a3c3ca26c1a0309197d28e032f27e7 100644 (file)
@@ -390,6 +390,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
 
 struct ath_vif {
        int av_bslot;
+       __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
        enum nl80211_iftype av_opmode;
        struct ath_buf *av_bcbuf;
        struct ath_tx_control av_btxctl;
@@ -406,7 +407,7 @@ struct ath_vif {
  * number of beacon intervals, the game's up.
  */
 #define BSTUCK_THRESH                  (9 * ATH_BCBUF)
-#define        ATH_BCBUF                       1
+#define        ATH_BCBUF                       4
 #define ATH_DEFAULT_BINTVAL            100 /* TU */
 #define ATH_DEFAULT_BMISS_LIMIT        10
 #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
index 039c78136c50e2b2de7b884412bb8ac7701803f7..3fd1b86a9b394abc5a0dc612b2a98fbf9ccb0f5f 100644 (file)
@@ -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",