aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-03-12 15:53:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:12:46 -0400
commit4ed96f04f8a1869757f4dd4a9283a18ec63c442f (patch)
tree09048c068bd2cb59a560bd937630636eaacac84c
parent11432379fd2a3854a3408424d8dcd99afd811573 (diff)
ath9k: Add support for multiple virtual AP interfaces
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>
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath9k/beacon.c50
2 files changed, 27 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index b64be8e9a690..5afd244ea6a3 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -390,6 +390,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
390 390
391struct ath_vif { 391struct ath_vif {
392 int av_bslot; 392 int av_bslot;
393 __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
393 enum nl80211_iftype av_opmode; 394 enum nl80211_iftype av_opmode;
394 struct ath_buf *av_bcbuf; 395 struct ath_buf *av_bcbuf;
395 struct ath_tx_control av_btxctl; 396 struct ath_tx_control av_btxctl;
@@ -406,7 +407,7 @@ struct ath_vif {
406 * number of beacon intervals, the game's up. 407 * number of beacon intervals, the game's up.
407 */ 408 */
408#define BSTUCK_THRESH (9 * ATH_BCBUF) 409#define BSTUCK_THRESH (9 * ATH_BCBUF)
409#define ATH_BCBUF 1 410#define ATH_BCBUF 4
410#define ATH_DEFAULT_BINTVAL 100 /* TU */ 411#define ATH_DEFAULT_BINTVAL 100 /* TU */
411#define ATH_DEFAULT_BMISS_LIMIT 10 412#define ATH_DEFAULT_BMISS_LIMIT 10
412#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) 413#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 039c78136c50..3fd1b86a9b39 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -153,6 +153,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
153 bf->bf_mpdu = skb; 153 bf->bf_mpdu = skb;
154 if (skb == NULL) 154 if (skb == NULL)
155 return NULL; 155 return NULL;
156 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
157 avp->tsf_adjust;
156 158
157 info = IEEE80211_SKB_CB(skb); 159 info = IEEE80211_SKB_CB(skb);
158 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 160 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
@@ -253,7 +255,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
253{ 255{
254 struct ath_softc *sc = aphy->sc; 256 struct ath_softc *sc = aphy->sc;
255 struct ath_vif *avp; 257 struct ath_vif *avp;
256 struct ieee80211_hdr *hdr;
257 struct ath_buf *bf; 258 struct ath_buf *bf;
258 struct sk_buff *skb; 259 struct sk_buff *skb;
259 __le64 tstamp; 260 __le64 tstamp;
@@ -316,42 +317,33 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
316 317
317 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; 318 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
318 sc->beacon.bc_tstamp = le64_to_cpu(tstamp); 319 sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
319 320 /* 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) { 321 if (avp->av_bslot > 0) {
327 u64 tsfadjust; 322 u64 tsfadjust;
328 __le64 val;
329 int intval; 323 int intval;
330 324
331 intval = sc->hw->conf.beacon_int ? 325 intval = sc->hw->conf.beacon_int ?
332 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; 326 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
333 327
334 /* 328 /*
335 * The beacon interval is in TU's; the TSF in usecs. 329 * Calculate the TSF offset for this beacon slot, i.e., the
336 * We figure out how many TU's to add to align the 330 * number of usecs that need to be added to the timestamp field
337 * timestamp then convert to TSF units and handle 331 * in Beacon and Probe Response frames. Beacon slot 0 is
338 * byte swapping before writing it in the frame. 332 * processed at the correct offset, so it does not require TSF
339 * The hardware will then add this each time a beacon 333 * adjustment. Other slots are adjusted to get the timestamp
340 * frame is sent. Note that we align vif's 1..N 334 * 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 */ 335 */
345 tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; 336 tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
346 val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ 337 avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
347 338
348 DPRINTF(sc, ATH_DBG_BEACON, 339 DPRINTF(sc, ATH_DBG_BEACON,
349 "stagger beacons, bslot %d intval %u tsfadjust %llu\n", 340 "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
350 avp->av_bslot, intval, (unsigned long long)tsfadjust); 341 avp->av_bslot, intval, (unsigned long long)tsfadjust);
351 342
352 hdr = (struct ieee80211_hdr *)skb->data; 343 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
353 memcpy(&hdr[1], &val, sizeof(val)); 344 avp->tsf_adjust;
354 } 345 } else
346 avp->tsf_adjust = cpu_to_le64(0);
355 347
356 bf->bf_mpdu = skb; 348 bf->bf_mpdu = skb;
357 bf->bf_buf_addr = bf->bf_dmacontext = 349 bf->bf_buf_addr = bf->bf_dmacontext =
@@ -447,8 +439,16 @@ void ath_beacon_tasklet(unsigned long data)
447 tsf = ath9k_hw_gettsf64(ah); 439 tsf = ath9k_hw_gettsf64(ah);
448 tsftu = TSF_TO_TU(tsf>>32, tsf); 440 tsftu = TSF_TO_TU(tsf>>32, tsf);
449 slot = ((tsftu % intval) * ATH_BCBUF) / intval; 441 slot = ((tsftu % intval) * ATH_BCBUF) / intval;
450 vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; 442 /*
451 aphy = sc->beacon.bslot_aphy[(slot + 1) % ATH_BCBUF]; 443 * Reverse the slot order to get slot 0 on the TBTT offset that does
444 * not require TSF adjustment and other slots adding
445 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
446 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
447 * and slot 0 is at correct offset to TBTT.
448 */
449 slot = ATH_BCBUF - slot - 1;
450 vif = sc->beacon.bslot[slot];
451 aphy = sc->beacon.bslot_aphy[slot];
452 452
453 DPRINTF(sc, ATH_DBG_BEACON, 453 DPRINTF(sc, ATH_DBG_BEACON,
454 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", 454 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",