ath9k: Implement hw_scan support

Implement hw_scan support for enabling multi-channel cuncurrency.

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>
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 26fc98b..c679a26 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -228,6 +228,7 @@
 	if (send_ps)
 		ath_chanctx_send_ps_frame(sc, false);
 
+	ath_offchannel_channel_change(sc);
 	mutex_unlock(&sc->mutex);
 }
 
@@ -253,6 +254,14 @@
 			INIT_LIST_HEAD(&ctx->acq[j]);
 	}
 	sc->cur_chan = &sc->chanctx[0];
+	ctx = &sc->offchannel.chan;
+	cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
+	INIT_LIST_HEAD(&ctx->vifs);
+	ctx->txpower = ATH_TXPOWER_MAX;
+	for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
+		INIT_LIST_HEAD(&ctx->acq[j]);
+	sc->offchannel.chan.offchannel = true;
+
 }
 
 void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
@@ -283,3 +292,25 @@
 
 	ath_set_channel(sc);
 }
+
+struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc)
+{
+	u8 i;
+
+	for (i = 0; i < ARRAY_SIZE(sc->chanctx); i++) {
+		if (!list_empty(&sc->chanctx[i].vifs))
+			return &sc->chanctx[i];
+	}
+
+	return &sc->chanctx[0];
+}
+
+void ath_chanctx_offchan_switch(struct ath_softc *sc,
+				struct ieee80211_channel *chan)
+{
+	struct cfg80211_chan_def chandef;
+
+	cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
+
+	ath_chanctx_switch(sc, &sc->offchannel.chan, &chandef);
+}