ath9k: fix a beacon enable handling bug

Backport of r44696

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

git-svn-id: svn://svn.openwrt.org/openwrt/branches/barrier_breaker@44697 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
nbd 2015-03-12 16:32:07 +00:00
parent 12c281e5eb
commit 8737792072
1 changed files with 85 additions and 0 deletions

View File

@ -1,3 +1,20 @@
commit 182a72b61971fc7120d6163b2077c06618c422a4
Author: Felix Fietkau <nbd@openwrt.org>
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 <nbd@openwrt.org>
commit 228ee4473b89118993c17ead26381c490c44f9fb
Author: Felix Fietkau <nbd@openwrt.org>
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;