add chaos_calmer branch
[15.05/openwrt.git] / package / kernel / mac80211 / patches / 307-ath9k-fix-tracking-of-enabled-AP-beacons.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Thu, 12 Mar 2015 17:10:50 +0100
3 Subject: [PATCH] ath9k: fix tracking of enabled AP beacons
4
5 sc->nbcnvifs tracks assigned beacon slots, not enabled beacons.
6 Therefore, it cannot be used to decide if cur_conf->enable_beacon (bool)
7 should be updated, or if beacons have been enabled already.
8 With the current code (depending on the order of calls), beacons often
9 do not get enabled in an AP+STA setup.
10 To fix tracking of enabled beacons, convert cur_conf->enable_beacon to a
11 bitmask of enabled beacon slots.
12
13 Cc: stable@vger.kernel.org
14 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
15 ---
16
17 --- a/drivers/net/wireless/ath/ath9k/beacon.c
18 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
19 @@ -219,12 +219,15 @@ void ath9k_beacon_remove_slot(struct ath
20         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
21         struct ath_vif *avp = (void *)vif->drv_priv;
22         struct ath_buf *bf = avp->av_bcbuf;
23 +       struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
24  
25         ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
26                 avp->av_bslot);
27  
28         tasklet_disable(&sc->bcon_tasklet);
29  
30 +       cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
31 +
32         if (bf && bf->bf_mpdu) {
33                 struct sk_buff *skb = bf->bf_mpdu;
34                 dma_unmap_single(sc->dev, bf->bf_buf_addr,
35 @@ -521,8 +524,7 @@ static bool ath9k_allow_beacon_config(st
36         }
37  
38         if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
39 -               if ((vif->type != NL80211_IFTYPE_AP) ||
40 -                   (sc->nbcnvifs > 1)) {
41 +               if (vif->type != NL80211_IFTYPE_AP) {
42                         ath_dbg(common, CONFIG,
43                                 "An AP interface is already present !\n");
44                         return false;
45 @@ -616,12 +618,14 @@ void ath9k_beacon_config(struct ath_soft
46          * enabling/disabling SWBA.
47          */
48         if (changed & BSS_CHANGED_BEACON_ENABLED) {
49 -               if (!bss_conf->enable_beacon &&
50 -                   (sc->nbcnvifs <= 1)) {
51 -                       cur_conf->enable_beacon = false;
52 -               } else if (bss_conf->enable_beacon) {
53 -                       cur_conf->enable_beacon = true;
54 -                       ath9k_cache_beacon_config(sc, ctx, bss_conf);
55 +               bool enabled = cur_conf->enable_beacon;
56 +
57 +               if (!bss_conf->enable_beacon) {
58 +                       cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
59 +               } else {
60 +                       cur_conf->enable_beacon |= BIT(avp->av_bslot);
61 +                       if (!enabled)
62 +                               ath9k_cache_beacon_config(sc, ctx, bss_conf);
63                 }
64         }
65  
66 --- a/drivers/net/wireless/ath/ath9k/common.h
67 +++ b/drivers/net/wireless/ath/ath9k/common.h
68 @@ -54,7 +54,7 @@ struct ath_beacon_config {
69         u16 dtim_period;
70         u16 bmiss_timeout;
71         u8 dtim_count;
72 -       bool enable_beacon;
73 +       u8 enable_beacon;
74         bool ibss_creator;
75         u32 nexttbtt;
76         u32 intval;