+static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct ath_softc *sc = data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ath_vif *avp = (void *)vif->drv_priv;
+
+ switch (sc->sc_ah->opmode) {
+ case NL80211_IFTYPE_ADHOC:
+ /* There can be only one vif available */
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+ /* configure beacon */
+ if (bss_conf->enable_beacon)
+ ath_beacon_config(sc, vif);
+ break;
+ case NL80211_IFTYPE_STATION:
+ /*
+ * Skip iteration if primary station vif's bss info
+ * was not changed
+ */
+ if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
+ break;
+
+ if (bss_conf->assoc) {
+ sc->sc_flags |= SC_OP_PRIM_STA_VIF;
+ avp->primary_sta_vif = true;
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Bss Info ASSOC %d, bssid: %pM\n",
+ bss_conf->aid, common->curbssid);
+ ath_beacon_config(sc, vif);
+ /*
+ * Request a re-configuration of Beacon related timers
+ * on the receipt of the first Beacon frame (i.e.,
+ * after time sync with the AP).
+ */
+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+ /* Reset rssi stats */
+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ath_vif *avp = (void *)vif->drv_priv;
+
+ /* Reconfigure bss info */
+ if (avp->primary_sta_vif && !bss_conf->assoc) {
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Bss Info DISASSOC %d, bssid %pM\n",
+ common->curaid, common->curbssid);
+ sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS);
+ avp->primary_sta_vif = false;
+ memset(common->curbssid, 0, ETH_ALEN);
+ common->curaid = 0;
+ }
+
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->hw, ath9k_bss_iter, sc);
+
+ /*
+ * None of station vifs are associated.
+ * Clear bssid & aid
+ */
+ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+ !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
+ ath9k_hw_write_associd(sc->sc_ah);
+ /* Stop ANI */
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ }
+}