diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-12 15:53:23 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:12:46 -0400 |
commit | 4ed96f04f8a1869757f4dd4a9283a18ec63c442f (patch) | |
tree | 09048c068bd2cb59a560bd937630636eaacac84c | |
parent | 11432379fd2a3854a3408424d8dcd99afd811573 (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.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/beacon.c | 50 |
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 | ||
391 | struct ath_vif { | 391 | struct 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", |