|
|
|
@ -76,22 +76,13 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, |
|
|
|
|
ds = bf->bf_desc; |
|
|
|
|
flags = ATH9K_TXDESC_NOACK; |
|
|
|
|
|
|
|
|
|
if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || |
|
|
|
|
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && |
|
|
|
|
(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { |
|
|
|
|
ds->ds_link = bf->bf_daddr; /* self-linked */ |
|
|
|
|
flags |= ATH9K_TXDESC_VEOL; |
|
|
|
|
/* Let hardware handle antenna switching. */ |
|
|
|
|
antenna = 0; |
|
|
|
|
} else { |
|
|
|
|
ds->ds_link = 0; |
|
|
|
|
/*
|
|
|
|
|
* Switch antenna every beacon. |
|
|
|
|
* Should only switch every beacon period, not for every SWBA |
|
|
|
|
* XXX assumes two antennae |
|
|
|
|
*/ |
|
|
|
|
antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); |
|
|
|
|
} |
|
|
|
|
ds->ds_link = 0; |
|
|
|
|
/*
|
|
|
|
|
* Switch antenna every beacon. |
|
|
|
|
* Should only switch every beacon period, not for every SWBA |
|
|
|
|
* XXX assumes two antennae |
|
|
|
|
*/ |
|
|
|
|
antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); |
|
|
|
|
|
|
|
|
|
sband = &sc->sbands[common->hw->conf.channel->band]; |
|
|
|
|
rate = sband->bitrates[rateidx].hw_value; |
|
|
|
@ -215,36 +206,6 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, |
|
|
|
|
return bf; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Startup beacon transmission for adhoc mode when they are sent entirely |
|
|
|
|
* by the hardware using the self-linked descriptor + veol trick. |
|
|
|
|
*/ |
|
|
|
|
static void ath_beacon_start_adhoc(struct ath_softc *sc, |
|
|
|
|
struct ieee80211_vif *vif) |
|
|
|
|
{ |
|
|
|
|
struct ath_hw *ah = sc->sc_ah; |
|
|
|
|
struct ath_common *common = ath9k_hw_common(ah); |
|
|
|
|
struct ath_buf *bf; |
|
|
|
|
struct ath_vif *avp; |
|
|
|
|
struct sk_buff *skb; |
|
|
|
|
|
|
|
|
|
avp = (void *)vif->drv_priv; |
|
|
|
|
|
|
|
|
|
if (avp->av_bcbuf == NULL) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
bf = avp->av_bcbuf; |
|
|
|
|
skb = bf->bf_mpdu; |
|
|
|
|
|
|
|
|
|
ath_beacon_setup(sc, avp, bf, 0); |
|
|
|
|
|
|
|
|
|
/* NB: caller is known to have already stopped tx dma */ |
|
|
|
|
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); |
|
|
|
|
ath9k_hw_txstart(ah, sc->beacon.beaconq); |
|
|
|
|
ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", |
|
|
|
|
sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) |
|
|
|
|
{ |
|
|
|
|
struct ath_softc *sc = aphy->sc; |
|
|
|
@ -265,7 +226,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) |
|
|
|
|
list_del(&avp->av_bcbuf->list); |
|
|
|
|
|
|
|
|
|
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || |
|
|
|
|
!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { |
|
|
|
|
sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC || |
|
|
|
|
sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) { |
|
|
|
|
int slot; |
|
|
|
|
/*
|
|
|
|
|
* Assign the vif to a beacon xmit slot. As |
|
|
|
@ -274,17 +236,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) |
|
|
|
|
avp->av_bslot = 0; |
|
|
|
|
for (slot = 0; slot < ATH_BCBUF; slot++) |
|
|
|
|
if (sc->beacon.bslot[slot] == NULL) { |
|
|
|
|
/*
|
|
|
|
|
* XXX hack, space out slots to better |
|
|
|
|
* deal with misses |
|
|
|
|
*/ |
|
|
|
|
if (slot+1 < ATH_BCBUF && |
|
|
|
|
sc->beacon.bslot[slot+1] == NULL) { |
|
|
|
|
avp->av_bslot = slot+1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
avp->av_bslot = slot; |
|
|
|
|
|
|
|
|
|
/* NB: keep looking for a double slot */ |
|
|
|
|
if (slot == 0 || !sc->beacon.bslot[slot-1]) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); |
|
|
|
|
sc->beacon.bslot[avp->av_bslot] = vif; |
|
|
|
@ -721,8 +677,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, |
|
|
|
|
* self-linked tx descriptor and let the hardware deal with things. |
|
|
|
|
*/ |
|
|
|
|
intval |= ATH9K_BEACON_ENA; |
|
|
|
|
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) |
|
|
|
|
ah->imask |= ATH9K_INT_SWBA; |
|
|
|
|
ah->imask |= ATH9K_INT_SWBA; |
|
|
|
|
|
|
|
|
|
ath_beaconq_config(sc); |
|
|
|
|
|
|
|
|
@ -732,10 +687,6 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, |
|
|
|
|
ath9k_beacon_init(sc, nexttbtt, intval); |
|
|
|
|
sc->beacon.bmisscnt = 0; |
|
|
|
|
ath9k_hw_set_interrupts(ah, ah->imask); |
|
|
|
|
|
|
|
|
|
/* FIXME: Handle properly when vif is NULL */ |
|
|
|
|
if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) |
|
|
|
|
ath_beacon_start_adhoc(sc, vif); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) |
|
|
|
|