ath9k: Summarize hw state per channel context
authorRajkumar Manoharan <rmanohar@qti.qualcomm.com>
Wed, 11 Jun 2014 10:48:03 +0000 (16:18 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 19 Jun 2014 19:49:18 +0000 (15:49 -0400)
Group and set hw state (opmode, primary_sta, beacon conf) per
channel context instead of whole list of vifs. This would allow
each channel context to run in different mode (STA/AP).

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/main.c

index d632f8f..a0c7279 100644 (file)
@@ -328,6 +328,9 @@ struct ath_chanctx {
        struct list_head vifs;
        struct list_head acq[IEEE80211_NUM_ACS];
 
+       /* do not dereference, use for comparison only */
+       struct ieee80211_vif *primary_sta;
+
        struct ath_beacon_config beacon;
        struct ath9k_hw_cal_data caldata;
        struct timespec tsf_ts;
@@ -438,7 +441,6 @@ struct ath_vif {
        struct ieee80211_vif *vif;
        struct ath_node mcast_node;
        int av_bslot;
-       bool primary_sta_vif;
        __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
        struct ath_buf *av_bcbuf;
        struct ath_chanctx *chanctx;
@@ -451,17 +453,22 @@ struct ath9k_vif_iter_data {
        u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
        u8 mask[ETH_ALEN]; /* bssid mask */
        bool has_hw_macaddr;
+       u8 slottime;
+       bool beacons;
 
        int naps;      /* number of AP vifs */
        int nmeshes;   /* number of mesh vifs */
        int nstations; /* number of station vifs */
        int nwds;      /* number of WDS vifs */
        int nadhocs;   /* number of adhoc vifs */
+       struct ieee80211_vif *primary_sta;
 };
 
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
-                              struct ieee80211_vif *vif,
+void ath9k_calculate_iter_data(struct ath_softc *sc,
+                              struct ath_chanctx *ctx,
                               struct ath9k_vif_iter_data *iter_data);
+void ath9k_calculate_summary_state(struct ath_softc *sc,
+                                  struct ath_chanctx *ctx);
 
 /*******************/
 /* Beacon Handling */
index c0ff015..d355392 100644 (file)
@@ -277,8 +277,8 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
 static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
        struct ath_vif *avp = (void *)vif->drv_priv;
+       struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
        u32 tsfadjust;
 
        if (avp->av_bslot == 0)
@@ -500,7 +500,6 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
                                      struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_vif *avp = (void *)vif->drv_priv;
 
        if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
                if ((vif->type != NL80211_IFTYPE_AP) ||
@@ -514,7 +513,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
        if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
                if ((vif->type == NL80211_IFTYPE_STATION) &&
                    test_bit(ATH_OP_BEACONS, &common->op_flags) &&
-                   !avp->primary_sta_vif) {
+                   vif != sc->cur_chan->primary_sta) {
                        ath_dbg(common, CONFIG,
                                "Beacon already configured for a station interface\n");
                        return false;
@@ -525,10 +524,11 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
 }
 
 static void ath9k_cache_beacon_config(struct ath_softc *sc,
+                                     struct ath_chanctx *ctx,
                                      struct ieee80211_bss_conf *bss_conf)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
+       struct ath_beacon_config *cur_conf = &ctx->beacon;
 
        ath_dbg(common, BEACON,
                "Caching beacon data for BSS: %pM\n", bss_conf->bssid);
@@ -564,20 +564,29 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
                         u32 changed)
 {
        struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-       struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
         struct ath_hw *ah = sc->sc_ah;
         struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       struct ath_chanctx *ctx = avp->chanctx;
+       struct ath_beacon_config *cur_conf;
        unsigned long flags;
        bool skip_beacon = false;
 
+       if (!ctx)
+               return;
+
+       cur_conf = &avp->chanctx->beacon;
        if (vif->type == NL80211_IFTYPE_AP)
                ath9k_set_tsfadjust(sc, vif);
 
        if (!ath9k_allow_beacon_config(sc, vif))
                return;
 
-       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
-               ath9k_cache_beacon_config(sc, bss_conf);
+       if (vif->type == NL80211_IFTYPE_STATION) {
+               ath9k_cache_beacon_config(sc, ctx, bss_conf);
+               if (ctx != sc->cur_chan)
+                       return;
+
                ath9k_set_beacon(sc);
                set_bit(ATH_OP_BEACONS, &common->op_flags);
                return;
@@ -593,10 +602,13 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
                        cur_conf->enable_beacon = false;
                } else if (bss_conf->enable_beacon) {
                        cur_conf->enable_beacon = true;
-                       ath9k_cache_beacon_config(sc, bss_conf);
+                       ath9k_cache_beacon_config(sc, ctx, bss_conf);
                }
        }
 
+       if (ctx != sc->cur_chan)
+               return;
+
        /*
         * Configure the HW beacon registers only when we have a valid
         * beacon interval.
index f230e2e..ce073e9 100644 (file)
@@ -750,13 +750,13 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 {
        struct ath_softc *sc = file->private_data;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ieee80211_hw *hw = sc->hw;
        struct ath9k_vif_iter_data iter_data;
+       struct ath_chanctx *ctx;
        char buf[512];
        unsigned int len = 0;
        ssize_t retval = 0;
        unsigned int reg;
-       u32 rxfilter;
+       u32 rxfilter, i;
 
        len += scnprintf(buf + len, sizeof(buf) - len,
                         "BSSID: %pM\n", common->curbssid);
@@ -826,14 +826,20 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 
        len += scnprintf(buf + len, sizeof(buf) - len, "\n");
 
-       ath9k_calculate_iter_data(hw, NULL, &iter_data);
-
-       len += scnprintf(buf + len, sizeof(buf) - len,
-                        "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
-                        " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
-                        iter_data.naps, iter_data.nstations, iter_data.nmeshes,
-                        iter_data.nwds, iter_data.nadhocs,
-                        sc->nvifs, sc->nbcnvifs);
+       i = 0;
+       ath_for_each_chanctx(sc, ctx) {
+               if (!ctx->assigned || list_empty(&ctx->vifs))
+                       continue;
+               ath9k_calculate_iter_data(sc, ctx, &iter_data);
+
+               len += scnprintf(buf + len, sizeof(buf) - len,
+                       "VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i",
+                       i++, iter_data.naps, iter_data.nstations,
+                       iter_data.nmeshes, iter_data.nwds);
+               len += scnprintf(buf + len, sizeof(buf) - len,
+                       " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+                       iter_data.nadhocs, sc->nvifs, sc->nbcnvifs);
+       }
 
        if (len > sizeof(buf))
                len = sizeof(buf);
index 6abdf99..9dfb820 100644 (file)
@@ -19,9 +19,6 @@
 #include "ath9k.h"
 #include "btcoex.h"
 
-static void ath9k_set_assoc_state(struct ath_softc *sc,
-                                 struct ieee80211_vif *vif);
-
 u8 ath9k_parse_mpdudensity(u8 mpdudensity)
 {
        /*
@@ -236,8 +233,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
                               sc->cur_chan->txpower, &sc->curtxpow);
 
        clear_bit(ATH_OP_HW_RESET, &common->op_flags);
-       ath9k_hw_set_interrupts(ah);
-       ath9k_hw_enable_interrupts(ah);
+       ath9k_calculate_summary_state(sc, sc->cur_chan);
 
        if (!sc->cur_chan->offchannel && start) {
                /* restore per chanctx TSF timer */
@@ -267,6 +263,10 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
        }
 
        sc->gtt_cnt = 0;
+
+       ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+
        ieee80211_wake_queues(sc->hw);
 
        ath9k_p2p_ps_timer(sc);
@@ -905,18 +905,29 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
                iter_data->has_hw_macaddr = true;
        }
 
+       if (!vif->bss_conf.use_short_slot)
+               iter_data->slottime = ATH9K_SLOT_TIME_20;
+
        switch (vif->type) {
        case NL80211_IFTYPE_AP:
                iter_data->naps++;
+               if (vif->bss_conf.enable_beacon)
+                       iter_data->beacons = true;
                break;
        case NL80211_IFTYPE_STATION:
                iter_data->nstations++;
+               if (vif->bss_conf.assoc && !iter_data->primary_sta)
+                       iter_data->primary_sta = vif;
                break;
        case NL80211_IFTYPE_ADHOC:
                iter_data->nadhocs++;
+               if (vif->bss_conf.enable_beacon)
+                       iter_data->beacons = true;
                break;
        case NL80211_IFTYPE_MESH_POINT:
                iter_data->nmeshes++;
+               if (vif->bss_conf.enable_beacon)
+                       iter_data->beacons = true;
                break;
        case NL80211_IFTYPE_WDS:
                iter_data->nwds++;
@@ -926,26 +937,12 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        }
 }
 
-static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-       struct ath_softc *sc = data;
-       struct ath_vif *avp = (void *)vif->drv_priv;
-
-       if (vif->type != NL80211_IFTYPE_STATION)
-               return;
-
-       if (avp->primary_sta_vif)
-               ath9k_set_assoc_state(sc, vif);
-}
-
 /* Called with sc->mutex held. */
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
-                              struct ieee80211_vif *vif,
+void ath9k_calculate_iter_data(struct ath_softc *sc,
+                              struct ath_chanctx *ctx,
                               struct ath9k_vif_iter_data *iter_data)
 {
-       struct ath_softc *sc = hw->priv;
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_vif *avp;
 
        /*
         * Pick the MAC address of the first interface as the new hardware
@@ -954,29 +951,80 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
+       iter_data->slottime = ATH9K_SLOT_TIME_9;
+
+       list_for_each_entry(avp, &ctx->vifs, list)
+               ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
+
+       if (ctx == &sc->offchannel.chan) {
+               struct ieee80211_vif *vif;
+
+               if (sc->offchannel.state < ATH_OFFCHANNEL_ROC_START)
+                       vif = sc->offchannel.scan_vif;
+               else
+                       vif = sc->offchannel.roc_vif;
+
+               if (vif)
+                       ath9k_vif_iter(iter_data, vif->addr, vif);
+               iter_data->beacons = false;
+       }
+}
+
+static void ath9k_set_assoc_state(struct ath_softc *sc,
+                                 struct ieee80211_vif *vif, bool changed)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+       unsigned long flags;
+
+       set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+       /* Set the AID, BSSID and do beacon-sync only when
+        * the HW opmode is STATION.
+        *
+        * But the primary bit is set above in any case.
+        */
+       if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+               return;
+
+       ether_addr_copy(common->curbssid, bss_conf->bssid);
+       common->curaid = bss_conf->aid;
+       ath9k_hw_write_associd(sc->sc_ah);
+
+       if (changed) {
+               common->last_rssi = ATH_RSSI_DUMMY_MARKER;
+               sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
-       if (vif)
-               ath9k_vif_iter(iter_data, vif->addr, vif);
+               spin_lock_irqsave(&sc->sc_pm_lock, flags);
+               sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+       }
 
-       /* Get list of all active MAC addresses */
-       ieee80211_iterate_active_interfaces_atomic(
-               sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-               ath9k_vif_iter, iter_data);
+       if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+               ath9k_mci_update_wlan_channels(sc, false);
 
-       memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
+       ath_dbg(common, CONFIG,
+               "Primary Station interface: %pM, BSSID: %pM\n",
+               vif->addr, common->curbssid);
 }
 
 /* Called with sc->mutex held. */
-static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
-                                         struct ieee80211_vif *vif)
+void ath9k_calculate_summary_state(struct ath_softc *sc,
+                                  struct ath_chanctx *ctx)
 {
-       struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_vif_iter_data iter_data;
-       enum nl80211_iftype old_opmode = ah->opmode;
 
-       ath9k_calculate_iter_data(hw, vif, &iter_data);
+       ath_chanctx_check_active(sc, ctx);
+
+       if (ctx != sc->cur_chan)
+               return;
+
+       ath9k_ps_wakeup(sc);
+       ath9k_calculate_iter_data(sc, ctx, &iter_data);
+
+       if (iter_data.has_hw_macaddr)
+               ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
        ath_hw_setbssidmask(common);
@@ -1004,19 +1052,48 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
        else
                ah->imask &= ~ATH9K_INT_TSFOOR;
 
+       ah->imask &= ~ATH9K_INT_SWBA;
+       if (ah->opmode == NL80211_IFTYPE_STATION) {
+               bool changed = (iter_data.primary_sta != ctx->primary_sta);
+
+               iter_data.beacons = true;
+               if (iter_data.primary_sta) {
+                       ath9k_set_assoc_state(sc, iter_data.primary_sta,
+                                             changed);
+                       if (!ctx->primary_sta ||
+                           !ctx->primary_sta->bss_conf.assoc)
+                               ctx->primary_sta = iter_data.primary_sta;
+               } else {
+                       ctx->primary_sta = NULL;
+                       memset(common->curbssid, 0, ETH_ALEN);
+                       common->curaid = 0;
+                       ath9k_hw_write_associd(sc->sc_ah);
+                       if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+                               ath9k_mci_update_wlan_channels(sc, true);
+               }
+       } else if (iter_data.beacons) {
+               ah->imask |= ATH9K_INT_SWBA;
+       }
        ath9k_hw_set_interrupts(ah);
 
-       /*
-        * If we are changing the opmode to STATION,
-        * a beacon sync needs to be done.
-        */
-       if (ah->opmode == NL80211_IFTYPE_STATION &&
-           old_opmode == NL80211_IFTYPE_AP &&
-           test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
-               ieee80211_iterate_active_interfaces_atomic(
-                       sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-                       ath9k_sta_vif_iter, sc);
+       if (iter_data.beacons)
+               set_bit(ATH_OP_BEACONS, &common->op_flags);
+       else
+               clear_bit(ATH_OP_BEACONS, &common->op_flags);
+
+       if (ah->slottime != iter_data.slottime) {
+               ah->slottime = iter_data.slottime;
+               ath9k_hw_init_global_settings(ah);
        }
+
+       if (iter_data.primary_sta)
+               set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+       else
+               clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+
+       ctx->primary_sta = iter_data.primary_sta;
+
+       ath9k_ps_restore(sc);
 }
 
 static int ath9k_add_interface(struct ieee80211_hw *hw,
@@ -1041,16 +1118,14 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
        sc->nvifs++;
 
-       ath9k_ps_wakeup(sc);
-       ath9k_calculate_summary_state(hw, vif);
-       ath9k_ps_restore(sc);
-
        if (ath9k_uses_beacons(vif->type))
                ath9k_beacon_assign_slot(sc, vif);
 
        avp->vif = vif;
-       if (!ath9k_use_chanctx)
+       if (!ath9k_use_chanctx) {
                avp->chanctx = sc->cur_chan;
+               list_add_tail(&avp->list, &avp->chanctx->vifs);
+       }
 
        an->sc = sc;
        an->sta = NULL;
@@ -1086,13 +1161,10 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
        vif->type = new_type;
        vif->p2p = p2p;
 
-       ath9k_ps_wakeup(sc);
-       ath9k_calculate_summary_state(hw, vif);
-       ath9k_ps_restore(sc);
-
        if (ath9k_uses_beacons(vif->type))
                ath9k_beacon_assign_slot(sc, vif);
-       ath_chanctx_check_active(sc, avp->chanctx);
+
+       ath9k_calculate_summary_state(sc, avp->chanctx);
 
        mutex_unlock(&sc->mutex);
        return 0;
@@ -1141,14 +1213,12 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 
        sc->nvifs--;
        sc->tx99_vif = NULL;
+       if (!ath9k_use_chanctx)
+               list_del(&avp->list);
 
        if (ath9k_uses_beacons(vif->type))
                ath9k_beacon_remove_slot(sc, vif);
 
-       ath9k_ps_wakeup(sc);
-       ath9k_calculate_summary_state(hw, NULL);
-       ath9k_ps_restore(sc);
-
        ath_tx_node_cleanup(sc, &avp->mcast_node);
 
        mutex_unlock(&sc->mutex);
@@ -1585,58 +1655,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
        return ret;
 }
 
-static void ath9k_set_assoc_state(struct ath_softc *sc,
-                                 struct ieee80211_vif *vif)
-{
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_vif *avp = (void *)vif->drv_priv;
-       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-       unsigned long flags;
-
-       set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
-       avp->primary_sta_vif = true;
-
-       /*
-        * Set the AID, BSSID and do beacon-sync only when
-        * the HW opmode is STATION.
-        *
-        * But the primary bit is set above in any case.
-        */
-       if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
-               return;
-
-       memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-       common->curaid = bss_conf->aid;
-       ath9k_hw_write_associd(sc->sc_ah);
-
-       common->last_rssi = ATH_RSSI_DUMMY_MARKER;
-       sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
-
-       spin_lock_irqsave(&sc->sc_pm_lock, flags);
-       sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
-       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
-
-       if (ath9k_hw_mci_is_enabled(sc->sc_ah))
-               ath9k_mci_update_wlan_channels(sc, false);
-
-       ath_dbg(common, CONFIG,
-               "Primary Station interface: %pM, BSSID: %pM\n",
-               vif->addr, common->curbssid);
-}
-
-static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-       struct ath_softc *sc = data;
-       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-       if (test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
-               return;
-
-       if (bss_conf->assoc)
-               ath9k_set_assoc_state(sc, vif);
-}
-
 void ath9k_p2p_ps_timer(void *priv)
 {
        struct ath_softc *sc = priv;
@@ -1646,7 +1664,7 @@ void ath9k_p2p_ps_timer(void *priv)
        struct ath_node *an;
        u32 tsf;
 
-       if (!avp)
+       if (!avp || avp->chanctx != sc->cur_chan)
                return;
 
        tsf = ath9k_hw_gettsf32(sc->sc_ah);
@@ -1721,28 +1739,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
                ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
                        bss_conf->bssid, bss_conf->assoc);
 
-               if (avp->primary_sta_vif && !bss_conf->assoc) {
-                       clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
-                       avp->primary_sta_vif = false;
-
-                       if (ah->opmode == NL80211_IFTYPE_STATION)
-                               clear_bit(ATH_OP_BEACONS, &common->op_flags);
-               }
-
-               ieee80211_iterate_active_interfaces_atomic(
-                       sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-                       ath9k_bss_assoc_iter, sc);
-
-               if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags) &&
-                   ah->opmode == NL80211_IFTYPE_STATION) {
-                       memset(common->curbssid, 0, ETH_ALEN);
-                       common->curaid = 0;
-                       ath9k_hw_write_associd(sc->sc_ah);
-                       if (ath9k_hw_mci_is_enabled(sc->sc_ah))
-                               ath9k_mci_update_wlan_channels(sc, true);
-               }
-
-               ath_chanctx_check_active(sc, avp->chanctx);
+               ath9k_calculate_summary_state(sc, avp->chanctx);
        }
 
        if (changed & BSS_CHANGED_IBSS) {
@@ -1752,10 +1749,14 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
-           (changed & BSS_CHANGED_BEACON_INT))
+           (changed & BSS_CHANGED_BEACON_INT)) {
+               if (changed & BSS_CHANGED_BEACON_ENABLED)
+                       ath9k_calculate_summary_state(sc, avp->chanctx);
                ath9k_beacon_config(sc, vif, changed);
+       }
 
-       if (changed & BSS_CHANGED_ERP_SLOT) {
+       if ((avp->chanctx == sc->cur_chan) &&
+           (changed & BSS_CHANGED_ERP_SLOT)) {
                if (bss_conf->use_short_slot)
                        slottime = 9;
                else
@@ -2500,7 +2501,7 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
        mutex_lock(&sc->mutex);
        avp->chanctx = ctx;
        list_add_tail(&avp->list, &ctx->vifs);
-       ath_chanctx_check_active(sc, ctx);
+       ath9k_calculate_summary_state(sc, ctx);
        mutex_unlock(&sc->mutex);
 
        return 0;
@@ -2517,7 +2518,7 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
        mutex_lock(&sc->mutex);
        avp->chanctx = NULL;
        list_del(&avp->list);
-       ath_chanctx_check_active(sc, ctx);
+       ath9k_calculate_summary_state(sc, ctx);
        mutex_unlock(&sc->mutex);
 }