ath9k: Handle channel initialization for AP mode

Hostapd now passes the HT parameters through the config()
callback, use these to set the appropriate channel in AP mode.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 437e38a..e05eb1f 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -622,35 +622,35 @@
 	return -1;
 }
 
+/* ext_chan_offset: (-1, 0, 1) (below, none, above) */
+
 static u32 ath_get_extchanmode(struct ath_softc *sc,
 			       struct ieee80211_channel *chan,
-			       struct ieee80211_bss_conf *bss_conf)
+			       int ext_chan_offset,
+			       enum ath9k_ht_macmode tx_chan_width)
 {
 	u32 chanmode = 0;
-	u8 ext_chan_offset = bss_conf->ht.secondary_channel_offset;
-	enum ath9k_ht_macmode tx_chan_width = (bss_conf->ht.width_40_ok) ?
-		ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
 
 	switch (chan->band) {
 	case IEEE80211_BAND_2GHZ:
-		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
+		if ((ext_chan_offset == 0) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_20))
 			chanmode = CHANNEL_G_HT20;
-		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
+		if ((ext_chan_offset == 1) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_G_HT40PLUS;
-		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
+		if ((ext_chan_offset == -1) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_G_HT40MINUS;
 		break;
 	case IEEE80211_BAND_5GHZ:
-		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
+		if ((ext_chan_offset == 0) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_20))
 			chanmode = CHANNEL_A_HT20;
-		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
+		if ((ext_chan_offset == 1) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_A_HT40PLUS;
-		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
+		if ((ext_chan_offset == -1) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_A_HT40MINUS;
 		break;
@@ -841,6 +841,18 @@
 	}
 }
 
+static inline int ath_sec_offset(u8 ext_offset)
+{
+	if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE)
+		return 0;
+	else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+		return 1;
+	else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+		return -1;
+
+	return 0;
+}
+
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf)
@@ -892,13 +904,14 @@
 		}
 
 		if (hw->conf.ht.enabled) {
-			sc->sc_ah->ah_channels[pos].chanmode =
-				ath_get_extchanmode(sc, curchan, bss_conf);
+			int offset =
+				ath_sec_offset(bss_conf->ht.secondary_channel_offset);
+			sc->tx_chan_width = (bss_conf->ht.width_40_ok) ?
+				ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
 
-			if (bss_conf->ht.width_40_ok)
-				sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
-			else
-				sc->tx_chan_width = ATH9K_HT_MACMODE_20;
+			sc->sc_ah->ah_channels[pos].chanmode =
+				ath_get_extchanmode(sc, curchan,
+						    offset, sc->tx_chan_width);
 		} else {
 			sc->sc_ah->ah_channels[pos].chanmode =
 				(curchan->band == IEEE80211_BAND_2GHZ) ?
@@ -2171,9 +2184,22 @@
 			(curchan->band == IEEE80211_BAND_2GHZ) ?
 			CHANNEL_G : CHANNEL_A;
 
-		if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
+		if ((sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) &&
+		    (conf->ht.enabled)) {
+			sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ?
+				ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
+
+			sc->sc_ah->ah_channels[pos].chanmode =
+				ath_get_extchanmode(sc, curchan,
+						    conf->ht.sec_chan_offset,
+						    sc->tx_chan_width);
+		}
+
+		if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) {
 			DPRINTF(sc, ATH_DBG_FATAL,
 				"%s: Unable to set channel\n", __func__);
+			return -EINVAL;
+		}
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_HT)