ath9k: Revamp wireless mode usage

Use a single enum for managing modes, store supported modes by
the HW in a bitmask.
Register legacy rates with mac80211 only at init.

Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c
index 05e10c4..62e2888 100644
--- a/drivers/net/wireless/ath9k/regd.c
+++ b/drivers/net/wireless/ath9k/regd.c
@@ -131,46 +131,45 @@
 	return false;
 }
 
-static u32
+static void
 ath9k_regd_get_wmodes_nreg(struct ath_hal *ah,
 			   struct country_code_to_enum_rd *country,
-			   struct regDomain *rd5GHz)
+			   struct regDomain *rd5GHz,
+			   unsigned long *modes_allowed)
 {
-	u32 modesAvail;
+	bitmap_copy(modes_allowed, ah->ah_caps.wireless_modes, ATH9K_MODE_MAX);
 
-	modesAvail = ah->ah_caps.wireless_modes;
+	if (test_bit(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) &&
+	    (!country->allow11g))
+		clear_bit(ATH9K_MODE_11G, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11G) && (!country->allow11g))
-		modesAvail &= ~ATH9K_MODE_SEL_11G;
-	if ((modesAvail & ATH9K_MODE_SEL_11A) &&
+	if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) &&
 	    (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a)))
-		modesAvail &= ~ATH9K_MODE_SEL_11A;
+		clear_bit(ATH9K_MODE_11A, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11NG_HT20)
+	if (test_bit(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes)
 	    && (!country->allow11ng20))
-		modesAvail &= ~ATH9K_MODE_SEL_11NG_HT20;
+		clear_bit(ATH9K_MODE_11NG_HT20, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11NA_HT20)
+	if (test_bit(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes)
 	    && (!country->allow11na20))
-		modesAvail &= ~ATH9K_MODE_SEL_11NA_HT20;
+		clear_bit(ATH9K_MODE_11NA_HT20, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11NG_HT40PLUS) &&
+	if (test_bit(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) &&
 	    (!country->allow11ng40))
-		modesAvail &= ~ATH9K_MODE_SEL_11NG_HT40PLUS;
+		clear_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11NG_HT40MINUS) &&
+	if (test_bit(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) &&
 	    (!country->allow11ng40))
-		modesAvail &= ~ATH9K_MODE_SEL_11NG_HT40MINUS;
+		clear_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11NA_HT40PLUS) &&
+	if (test_bit(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) &&
 	    (!country->allow11na40))
-		modesAvail &= ~ATH9K_MODE_SEL_11NA_HT40PLUS;
+		clear_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed);
 
-	if ((modesAvail & ATH9K_MODE_SEL_11NA_HT40MINUS) &&
+	if (test_bit(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) &&
 	    (!country->allow11na40))
-		modesAvail &= ~ATH9K_MODE_SEL_11NA_HT40MINUS;
-
-	return modesAvail;
+		clear_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed);
 }
 
 bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah)
@@ -545,10 +544,10 @@
 		}
 	}
 
-	if (cm->mode & (ATH9K_MODE_SEL_11A |
-			ATH9K_MODE_SEL_11NA_HT20 |
-			ATH9K_MODE_SEL_11NA_HT40PLUS |
-			ATH9K_MODE_SEL_11NA_HT40MINUS)) {
+	if ((cm->mode == ATH9K_MODE_11A) ||
+	    (cm->mode == ATH9K_MODE_11NA_HT20) ||
+	    (cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
+	    (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) {
 		if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A))
 			privFlags |= CHANNEL_DISALLOW_ADHOC;
 	}
@@ -618,10 +617,9 @@
 			 u32 maxchans,
 			 u32 *nchans, u8 *regclassids,
 			 u32 maxregids, u32 *nregids, u16 cc,
-			 u32 modeSelect, bool enableOutdoor,
+			 bool enableOutdoor,
 			 bool enableExtendedChannels)
 {
-	u32 modesAvail;
 	u16 maxChan = 7000;
 	struct country_code_to_enum_rd *country = NULL;
 	struct regDomain rd5GHz, rd2GHz;
@@ -631,11 +629,13 @@
 	u8 ctl;
 	int regdmn;
 	u16 chanSep;
+	unsigned long *modes_avail;
+	DECLARE_BITMAP(modes_allowed, ATH9K_MODE_MAX);
 
-	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: cc %u mode 0x%x%s%s\n",
-		 __func__, cc, modeSelect,
-		 enableOutdoor ? " Enable outdoor" : " ",
-		 enableExtendedChannels ? " Enable ecm" : "");
+	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: cc %u %s %s\n",
+		 __func__, cc,
+		 enableOutdoor ? "Enable outdoor" : "",
+		 enableExtendedChannels ? "Enable ecm" : "");
 
 	if (!ath9k_regd_is_ccode_valid(ah, cc)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
@@ -726,9 +726,11 @@
 	}
 
 	if (country == NULL) {
-		modesAvail = ah->ah_caps.wireless_modes;
+		modes_avail = ah->ah_caps.wireless_modes;
 	} else {
-		modesAvail = ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz);
+		ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed);
+		modes_avail = modes_allowed;
+
 		if (!enableOutdoor)
 			maxChan = country->outdoorChanStart;
 	}
@@ -745,19 +747,12 @@
 		struct RegDmnFreqBand *fband = NULL, *freqs;
 		int8_t low_adj = 0, hi_adj = 0;
 
-		if ((cm->mode & modeSelect) == 0) {
+		if (!test_bit(cm->mode, modes_avail)) {
 			DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-				"%s: skip mode 0x%x flags 0x%x\n",
+				"%s: !avail mode %d flags 0x%x\n",
 				__func__, cm->mode, cm->flags);
 			continue;
 		}
-		if ((cm->mode & modesAvail) == 0) {
-			DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-				"%s: !avail mode 0x%x (0x%x) flags 0x%x\n",
-				__func__, modesAvail, cm->mode,
-				cm->flags);
-			continue;
-		}
 		if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) {
 			DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
 				"%s: channels 0x%x not supported "
@@ -767,25 +762,25 @@
 		}
 
 		switch (cm->mode) {
-		case ATH9K_MODE_SEL_11A:
-		case ATH9K_MODE_SEL_11NA_HT20:
-		case ATH9K_MODE_SEL_11NA_HT40PLUS:
-		case ATH9K_MODE_SEL_11NA_HT40MINUS:
+		case ATH9K_MODE_11A:
+		case ATH9K_MODE_11NA_HT20:
+		case ATH9K_MODE_11NA_HT40PLUS:
+		case ATH9K_MODE_11NA_HT40MINUS:
 			rd = &rd5GHz;
 			channelBM = rd->chan11a;
 			freqs = &regDmn5GhzFreq[0];
 			ctl = rd->conformanceTestLimit;
 			break;
-		case ATH9K_MODE_SEL_11B:
+		case ATH9K_MODE_11B:
 			rd = &rd2GHz;
 			channelBM = rd->chan11b;
 			freqs = &regDmn2GhzFreq[0];
 			ctl = rd->conformanceTestLimit | CTL_11B;
 			break;
-		case ATH9K_MODE_SEL_11G:
-		case ATH9K_MODE_SEL_11NG_HT20:
-		case ATH9K_MODE_SEL_11NG_HT40PLUS:
-		case ATH9K_MODE_SEL_11NG_HT40MINUS:
+		case ATH9K_MODE_11G:
+		case ATH9K_MODE_11NG_HT20:
+		case ATH9K_MODE_11NG_HT40PLUS:
+		case ATH9K_MODE_11NG_HT40MINUS:
 			rd = &rd2GHz;
 			channelBM = rd->chan11g;
 			freqs = &regDmn2Ghz11gFreq[0];
@@ -801,13 +796,13 @@
 		if (ath9k_regd_is_chan_bm_zero(channelBM))
 			continue;
 
-		if ((cm->mode == ATH9K_MODE_SEL_11NA_HT40PLUS) ||
-		    (cm->mode == ATH9K_MODE_SEL_11NG_HT40PLUS)) {
+		if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
+		    (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) {
 			hi_adj = -20;
 		}
 
-		if ((cm->mode == ATH9K_MODE_SEL_11NA_HT40MINUS) ||
-		    (cm->mode == ATH9K_MODE_SEL_11NG_HT40MINUS)) {
+		if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) ||
+		    (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) {
 			low_adj = 20;
 		}