Commit 4ed96f04 authored by Jouni Malinen's avatar Jouni Malinen Committed by John W. Linville

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: default avatarJouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 11432379
...@@ -390,6 +390,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid ...@@ -390,6 +390,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
struct ath_vif { struct ath_vif {
int av_bslot; int av_bslot;
__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
enum nl80211_iftype av_opmode; enum nl80211_iftype av_opmode;
struct ath_buf *av_bcbuf; struct ath_buf *av_bcbuf;
struct ath_tx_control av_btxctl; struct ath_tx_control av_btxctl;
...@@ -406,7 +407,7 @@ struct ath_vif { ...@@ -406,7 +407,7 @@ struct ath_vif {
* number of beacon intervals, the game's up. * number of beacon intervals, the game's up.
*/ */
#define BSTUCK_THRESH (9 * ATH_BCBUF) #define BSTUCK_THRESH (9 * ATH_BCBUF)
#define ATH_BCBUF 1 #define ATH_BCBUF 4
#define ATH_DEFAULT_BINTVAL 100 /* TU */ #define ATH_DEFAULT_BINTVAL 100 /* TU */
#define ATH_DEFAULT_BMISS_LIMIT 10 #define ATH_DEFAULT_BMISS_LIMIT 10
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
......
...@@ -153,6 +153,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, ...@@ -153,6 +153,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
bf->bf_mpdu = skb; bf->bf_mpdu = skb;
if (skb == NULL) if (skb == NULL)
return NULL; return NULL;
((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
avp->tsf_adjust;
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 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,7 +255,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
{ {
struct ath_softc *sc = aphy->sc; struct ath_softc *sc = aphy->sc;
struct ath_vif *avp; struct ath_vif *avp;
struct ieee80211_hdr *hdr;
struct ath_buf *bf; struct ath_buf *bf;
struct sk_buff *skb; struct sk_buff *skb;
__le64 tstamp; __le64 tstamp;
...@@ -316,42 +317,33 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) ...@@ -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; tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
sc->beacon.bc_tstamp = le64_to_cpu(tstamp); sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
/* Calculate a TSF adjustment factor required for staggered beacons. */
/*
* 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.
*/
if (avp->av_bslot > 0) { if (avp->av_bslot > 0) {
u64 tsfadjust; u64 tsfadjust;
__le64 val;
int intval; int intval;
intval = sc->hw->conf.beacon_int ? intval = sc->hw->conf.beacon_int ?
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
/* /*
* The beacon interval is in TU's; the TSF in usecs. * Calculate the TSF offset for this beacon slot, i.e., the
* We figure out how many TU's to add to align the * number of usecs that need to be added to the timestamp field
* timestamp then convert to TSF units and handle * in Beacon and Probe Response frames. Beacon slot 0 is
* byte swapping before writing it in the frame. * processed at the correct offset, so it does not require TSF
* The hardware will then add this each time a beacon * adjustment. Other slots are adjusted to get the timestamp
* frame is sent. Note that we align vif's 1..N * close to the TBTT for the BSS.
* 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.
*/ */
tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
DPRINTF(sc, ATH_DBG_BEACON, DPRINTF(sc, ATH_DBG_BEACON,
"stagger beacons, bslot %d intval %u tsfadjust %llu\n", "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
avp->av_bslot, intval, (unsigned long long)tsfadjust); avp->av_bslot, intval, (unsigned long long)tsfadjust);
hdr = (struct ieee80211_hdr *)skb->data; ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
memcpy(&hdr[1], &val, sizeof(val)); avp->tsf_adjust;
} } else
avp->tsf_adjust = cpu_to_le64(0);
bf->bf_mpdu = skb; bf->bf_mpdu = skb;
bf->bf_buf_addr = bf->bf_dmacontext = bf->bf_buf_addr = bf->bf_dmacontext =
...@@ -447,8 +439,16 @@ void ath_beacon_tasklet(unsigned long data) ...@@ -447,8 +439,16 @@ void ath_beacon_tasklet(unsigned long data)
tsf = ath9k_hw_gettsf64(ah); tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf); tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval; 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, DPRINTF(sc, ATH_DBG_BEACON,
"slot %d [tsf %llu tsftu %u intval %u] vif %p\n", "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment