From 873779207228d20b70f9ad9aaeb844b3df17f84e Mon Sep 17 00:00:00 2001 From: nbd Date: Thu, 12 Mar 2015 16:32:07 +0000 Subject: [PATCH] ath9k: fix a beacon enable handling bug Backport of r44696 Signed-off-by: Felix Fietkau git-svn-id: svn://svn.openwrt.org/openwrt/branches/barrier_breaker@44697 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../mac80211/patches/300-pending_work.patch | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index 10c5cad..b391d58 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,3 +1,20 @@ +commit 182a72b61971fc7120d6163b2077c06618c422a4 +Author: Felix Fietkau +Date: Thu Mar 12 17:10:50 2015 +0100 + + ath9k: fix tracking of enabled AP beacons + + 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: Felix Fietkau + commit 228ee4473b89118993c17ead26381c490c44f9fb Author: Felix Fietkau Date: Sun Nov 30 20:34:16 2014 +0100 @@ -3552,3 +3569,71 @@ Date: Mon May 19 21:20:49 2014 +0200 break; default: ath_err(common, "Invalid TX queue type: %u\n", type); +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -223,12 +223,15 @@ void ath9k_beacon_remove_slot(struct ath + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_vif *avp = (void *)vif->drv_priv; + struct ath_buf *bf = avp->av_bcbuf; ++ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; + + ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n", + avp->av_bslot); + + tasklet_disable(&sc->bcon_tasklet); + ++ cur_conf->enable_beacon &= ~BIT(avp->av_bslot); ++ + if (bf && bf->bf_mpdu) { + struct sk_buff *skb = bf->bf_mpdu; + dma_unmap_single(sc->dev, bf->bf_buf_addr, +@@ -503,8 +506,7 @@ static bool ath9k_allow_beacon_config(st + struct ath_vif *avp = (void *)vif->drv_priv; + + if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { +- if ((vif->type != NL80211_IFTYPE_AP) || +- (sc->nbcnvifs > 1)) { ++ if (vif->type != NL80211_IFTYPE_AP) { + ath_dbg(common, CONFIG, + "An AP interface is already present !\n"); + return false; +@@ -567,6 +569,7 @@ void ath9k_beacon_config(struct ath_soft + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); ++ struct ath_vif *avp = (void *)vif->drv_priv; + unsigned long flags; + bool skip_beacon = false; + +@@ -588,12 +591,14 @@ void ath9k_beacon_config(struct ath_soft + * enabling/disabling SWBA. + */ + if (changed & BSS_CHANGED_BEACON_ENABLED) { +- if (!bss_conf->enable_beacon && +- (sc->nbcnvifs <= 1)) { +- cur_conf->enable_beacon = false; +- } else if (bss_conf->enable_beacon) { +- cur_conf->enable_beacon = true; +- ath9k_cache_beacon_config(sc, bss_conf); ++ bool enabled = cur_conf->enable_beacon; ++ ++ if (!bss_conf->enable_beacon) { ++ cur_conf->enable_beacon &= ~BIT(avp->av_bslot); ++ } else { ++ cur_conf->enable_beacon |= BIT(avp->av_bslot); ++ if (!enabled) ++ ath9k_cache_beacon_config(sc, bss_conf); + } + } + +--- a/drivers/net/wireless/ath/ath9k/common.h ++++ b/drivers/net/wireless/ath/ath9k/common.h +@@ -53,7 +53,7 @@ struct ath_beacon_config { + u16 dtim_period; + u16 bmiss_timeout; + u8 dtim_count; +- bool enable_beacon; ++ u8 enable_beacon; + bool ibss_creator; + u32 nexttbtt; + u32 intval;