Commit 7f676736 authored by Felix Fietkau's avatar Felix Fietkau Committed by Sasha Levin

ath9k: fix tracking of enabled AP beacons

[ Upstream commit 1cf48f22 ]

sc->nbcnvifs tracks assigned beacon slots, not enabled beacons.
Therefore, it cannot be used to decide if cur_conf->enable_beacon (bool)
should be updated, or if beacons have been enabled already.
With the current code (depending on the order of calls), beacons often
do not get enabled in an AP+STA setup.
To fix tracking of enabled beacons, convert cur_conf->enable_beacon to a
bitmask of enabled beacon slots.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent 9786bf2b
...@@ -218,12 +218,15 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif) ...@@ -218,12 +218,15 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_vif *avp = (void *)vif->drv_priv; struct ath_vif *avp = (void *)vif->drv_priv;
struct ath_buf *bf = avp->av_bcbuf; struct ath_buf *bf = avp->av_bcbuf;
struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n", ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
avp->av_bslot); avp->av_bslot);
tasklet_disable(&sc->bcon_tasklet); tasklet_disable(&sc->bcon_tasklet);
cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
if (bf && bf->bf_mpdu) { if (bf && bf->bf_mpdu) {
struct sk_buff *skb = bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_buf_addr, dma_unmap_single(sc->dev, bf->bf_buf_addr,
...@@ -520,8 +523,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc, ...@@ -520,8 +523,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
} }
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
if ((vif->type != NL80211_IFTYPE_AP) || if (vif->type != NL80211_IFTYPE_AP) {
(sc->nbcnvifs > 1)) {
ath_dbg(common, CONFIG, ath_dbg(common, CONFIG,
"An AP interface is already present !\n"); "An AP interface is already present !\n");
return false; return false;
...@@ -615,11 +617,13 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, ...@@ -615,11 +617,13 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
* enabling/disabling SWBA. * enabling/disabling SWBA.
*/ */
if (changed & BSS_CHANGED_BEACON_ENABLED) { if (changed & BSS_CHANGED_BEACON_ENABLED) {
if (!bss_conf->enable_beacon && bool enabled = cur_conf->enable_beacon;
(sc->nbcnvifs <= 1)) {
cur_conf->enable_beacon = false; if (!bss_conf->enable_beacon) {
} else if (bss_conf->enable_beacon) { cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
cur_conf->enable_beacon = true; } else {
cur_conf->enable_beacon |= BIT(avp->av_bslot);
if (!enabled)
ath9k_cache_beacon_config(sc, ctx, bss_conf); ath9k_cache_beacon_config(sc, ctx, bss_conf);
} }
} }
......
...@@ -53,7 +53,7 @@ struct ath_beacon_config { ...@@ -53,7 +53,7 @@ struct ath_beacon_config {
u16 dtim_period; u16 dtim_period;
u16 bmiss_timeout; u16 bmiss_timeout;
u8 dtim_count; u8 dtim_count;
bool enable_beacon; u8 enable_beacon;
bool ibss_creator; bool ibss_creator;
u32 nexttbtt; u32 nexttbtt;
u32 intval; u32 intval;
......
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