Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bf30ff9 authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville
Browse files

ath9k: Fix panic when adding an AP interface



If a station interface is already assigned to a context
and is active and a second interface of type AP is added,
then beaconing on the new interface has to be begin only
after the BSS_CHANGED_BEACON_ENABLED flag is sent by mac80211
to the driver.

But, since we issue ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL as soon
as a new channel context is added, a switch occurs almost immediately
before BSS_CHANGED_BEACON_ENABLED is received. When a HW reset
is done for the new context, beacons are enabled for the
interface since "enable_beacon" in the BSS config maintained
in mac80211 is true - but the driver hasn't been notified yet.
This causes a panic, since the beacon interval is zero for this
interface and ath9k_cmn_beacon_config_ap() doesn't have a safety check.

Fix this panic by checking if the beacon params has been cached
for this context and use the "enable_beacon" flag maintained
locally in the driver. Also, recalculate the summary data
after the beacon params have been cached when BSS_CHANGED_BEACON_ENABLED
is received.

Signed-off-by: default avatarSujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 602607b6
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -916,8 +916,6 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
	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++;
@@ -1021,6 +1019,7 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath9k_vif_iter_data iter_data;
	struct ath_beacon_config *cur_conf;

	ath_chanctx_check_active(sc, ctx);

@@ -1037,8 +1036,11 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
	ath_hw_setbssidmask(common);

	if (iter_data.naps > 0) {
		cur_conf = &ctx->beacon;
		ath9k_hw_set_tsfadjust(ah, true);
		ah->opmode = NL80211_IFTYPE_AP;
		if (cur_conf->enable_beacon)
			iter_data.beacons = true;
	} else {
		ath9k_hw_set_tsfadjust(ah, false);

@@ -1695,9 +1697,9 @@ 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_INFO)) {
		ath9k_beacon_config(sc, vif, changed);
		if (changed & BSS_CHANGED_BEACON_ENABLED)
			ath9k_calculate_summary_state(sc, avp->chanctx);
		ath9k_beacon_config(sc, vif, changed);
	}

	if ((avp->chanctx == sc->cur_chan) &&