This fixes IBSS beacon transmissions without VEOL enabled
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/beacon.c | 12 +++---------
1 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index c8a4558..77face7 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -274,17 +274,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;
--
1.6.4.2
With VEOL, Beacon transmission in ad-hoc does not currently work.
I believe for larger ad-hoc networks, VEOL is too unreliable, as
it can get beacon transmissions stuck during synchronization.
Use SWBA based beacon trasmission similar to AP mode instead.
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/beacon.c | 63 +++++--------------------------
1 files changed, 10 insertions(+), 53 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 77face7..f43d85a 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -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
@@ -715,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);
@@ -726,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)
--
1.6.4.2
Le 13/05/2010 20:37, Felix Fietkau a ?crit :
> With VEOL, Beacon transmission in ad-hoc does not currently work.
> I believe for larger ad-hoc networks, VEOL is too unreliable, as
> it can get beacon transmissions stuck during synchronization.
> Use SWBA based beacon trasmission similar to AP mode instead.
>
> Signed-off-by: Felix Fietkau<[email protected]>
This is very good step toward IBSS. Thanks Felix!
Acked-by: Benoit Papillault <[email protected]>
> ---
> drivers/net/wireless/ath/ath9k/beacon.c | 63 +++++--------------------------
> 1 files changed, 10 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
> index 77face7..f43d85a 100644
> --- a/drivers/net/wireless/ath/ath9k/beacon.c
> +++ b/drivers/net/wireless/ath/ath9k/beacon.c
> @@ -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
> @@ -715,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);
>
> @@ -726,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)