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

Commit 86b89eed authored by Sujith's avatar Sujith Committed by John W. Linville
Browse files

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: default avatarSujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3b95978d
Loading
Loading
Loading
Loading
+15 −33
Original line number Diff line number Diff line
@@ -147,6 +147,19 @@ struct ath_desc {

#define ATH9K_RXDESC_INTREQ		0x0020

enum wireless_mode {
	ATH9K_MODE_11A = 0,
	ATH9K_MODE_11B = 2,
	ATH9K_MODE_11G = 3,
	ATH9K_MODE_11NA_HT20 = 6,
	ATH9K_MODE_11NG_HT20 = 7,
	ATH9K_MODE_11NA_HT40PLUS = 8,
	ATH9K_MODE_11NA_HT40MINUS = 9,
	ATH9K_MODE_11NG_HT40PLUS = 10,
	ATH9K_MODE_11NG_HT40MINUS = 11,
	ATH9K_MODE_MAX
};

enum ath9k_hw_caps {
	ATH9K_HW_CAP_CHAN_SPREAD		= BIT(0),
	ATH9K_HW_CAP_MIC_AESCCM                 = BIT(1),
@@ -190,7 +203,7 @@ enum ath9k_capability_type {

struct ath9k_hw_capabilities {
	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
	u32 wireless_modes;
	DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
	u16 total_queues;
	u16 keycache_size;
	u16 low_5ghz_chan, high_5ghz_chan;
@@ -813,37 +826,6 @@ struct ath_hal {
#endif
};

enum wireless_mode {
	WIRELESS_MODE_11a = 0,
	WIRELESS_MODE_11b = 2,
	WIRELESS_MODE_11g = 3,
	WIRELESS_MODE_11NA_HT20 = 6,
	WIRELESS_MODE_11NG_HT20 = 7,
	WIRELESS_MODE_11NA_HT40PLUS = 8,
	WIRELESS_MODE_11NA_HT40MINUS = 9,
	WIRELESS_MODE_11NG_HT40PLUS = 10,
	WIRELESS_MODE_11NG_HT40MINUS = 11,
	WIRELESS_MODE_MAX
};

enum {
	ATH9K_MODE_SEL_11A = 0x00001,
	ATH9K_MODE_SEL_11B = 0x00002,
	ATH9K_MODE_SEL_11G = 0x00004,
	ATH9K_MODE_SEL_11NG_HT20 = 0x00008,
	ATH9K_MODE_SEL_11NA_HT20 = 0x00010,
	ATH9K_MODE_SEL_11NG_HT40PLUS = 0x00020,
	ATH9K_MODE_SEL_11NG_HT40MINUS = 0x00040,
	ATH9K_MODE_SEL_11NA_HT40PLUS = 0x00080,
	ATH9K_MODE_SEL_11NA_HT40MINUS = 0x00100,
	ATH9K_MODE_SEL_2GHZ = (ATH9K_MODE_SEL_11B |
			       ATH9K_MODE_SEL_11G |
			       ATH9K_MODE_SEL_11NG_HT20),
	ATH9K_MODE_SEL_5GHZ = (ATH9K_MODE_SEL_11A |
			       ATH9K_MODE_SEL_11NA_HT20),
	ATH9K_MODE_SEL_ALL = 0xffffffff
};

struct chan_centers {
	u16 synth_center;
	u16 ctl_center;
@@ -865,7 +847,7 @@ bool ath9k_regd_init_channels(struct ath_hal *ah,
			      u32 maxchans, u32 *nchans,
			      u8 *regclassids,
			      u32 maxregids, u32 *nregids,
			      u16 cc, u32 modeSelect,
			      u16 cc,
			      bool enableOutdoor,
			      bool enableExtendedChannels);
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
	 * Calculate rate code.
	 * XXX everything at min xmit rate
	 */
	rix = sc->sc_minrateix;
	rix = 0;
	rt = sc->sc_currates;
	rate = rt->info[rix].rateCode;
	if (sc->sc_flags & ATH_PREAMBLE_SHORT)
+54 −96
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
	int i;

	memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
	rt = sc->sc_rates[mode];
	rt = ath9k_hw_getratetable(sc->sc_ah, mode);
	BUG_ON(!rt);

	for (i = 0; i < rt->rateCount; i++)
@@ -96,76 +96,52 @@ static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
	 * 11g, otherwise at 1Mb/s.
	 * XXX select protection rate index from rate table.
	 */
	sc->sc_protrix = (mode == WIRELESS_MODE_11g ? 1 : 0);
	/* rate index used to send mgt frames */
	sc->sc_minrateix = 0;
	sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0);
}

/*
 *  Select Rate Table
 *
 *  Based on the wireless mode passed in, the rate table in the ATH object
 *  is set to the mode specific rate table.  This also calls the callback
 *  function to set the rate in the protocol layer object.
 * Set up rate table (legacy rates)
 */

static int ath_rate_setup(struct ath_softc *sc, enum wireless_mode mode)
static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
{
	struct ath_hal *ah = sc->sc_ah;
	const struct ath9k_rate_table *rt;

	switch (mode) {
	case WIRELESS_MODE_11a:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11A);
		break;
	case WIRELESS_MODE_11b:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11B);
		break;
	case WIRELESS_MODE_11g:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11G);
		break;
	case WIRELESS_MODE_11NA_HT20:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NA_HT20);
		break;
	case WIRELESS_MODE_11NG_HT20:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NG_HT20);
	const struct ath9k_rate_table *rt = NULL;
	struct ieee80211_supported_band *sband;
	struct ieee80211_rate *rate;
	int i, maxrates;

	switch (band) {
	case IEEE80211_BAND_2GHZ:
		rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11G);
		break;
	case WIRELESS_MODE_11NA_HT40PLUS:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NA_HT40PLUS);
		break;
	case WIRELESS_MODE_11NA_HT40MINUS:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah,
				ATH9K_MODE_SEL_11NA_HT40MINUS);
		break;
	case WIRELESS_MODE_11NG_HT40PLUS:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NG_HT40PLUS);
		break;
	case WIRELESS_MODE_11NG_HT40MINUS:
		sc->sc_rates[mode] =
			ath9k_hw_getratetable(ah,
				ATH9K_MODE_SEL_11NG_HT40MINUS);
	case IEEE80211_BAND_5GHZ:
		rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11A);
		break;
	default:
		DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid mode %u\n",
			__func__, mode);
		return 0;
		break;
	}
	rt = sc->sc_rates[mode];

	if (rt == NULL)
		return 0;
		return;

	/* setup rate set in 802.11 protocol layer */
	ath_setup_rate(sc, mode, NORMAL_RATE, rt);
	sband = &sc->sbands[band];
	rate = sc->rates[band];

	return 1;
	if (rt->rateCount > ATH_RATE_MAX)
		maxrates = ATH_RATE_MAX;
	else
		maxrates = rt->rateCount;

	for (i = 0; i < maxrates; i++) {
		rate[i].bitrate = rt->info[i].rateKbps / 100;
		rate[i].hw_value = rt->info[i].rateCode;
		sband->n_bitrates++;
		DPRINTF(sc, ATH_DBG_CONFIG,
			"%s: Rate: %2dMbps, ratecode: %2d\n",
			__func__,
			rate[i].bitrate / 10,
			rate[i].hw_value);
	}
}

/*
@@ -191,7 +167,6 @@ static int ath_setup_channels(struct ath_softc *sc)
				      ATH_REGCLASSIDS_MAX,
				      &nregclass,
				      CTRY_DEFAULT,
				      ATH9K_MODE_SEL_ALL,
				      false,
				      1)) {
		u32 rd = ah->ah_currentRD;
@@ -267,43 +242,26 @@ static int ath_setup_channels(struct ath_softc *sc)
static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
{
	if (chan->chanmode == CHANNEL_A)
		return WIRELESS_MODE_11a;
		return ATH9K_MODE_11A;
	else if (chan->chanmode == CHANNEL_G)
		return WIRELESS_MODE_11g;
		return ATH9K_MODE_11G;
	else if (chan->chanmode == CHANNEL_B)
		return WIRELESS_MODE_11b;
		return ATH9K_MODE_11B;
	else if (chan->chanmode == CHANNEL_A_HT20)
		return WIRELESS_MODE_11NA_HT20;
		return ATH9K_MODE_11NA_HT20;
	else if (chan->chanmode == CHANNEL_G_HT20)
		return WIRELESS_MODE_11NG_HT20;
		return ATH9K_MODE_11NG_HT20;
	else if (chan->chanmode == CHANNEL_A_HT40PLUS)
		return WIRELESS_MODE_11NA_HT40PLUS;
		return ATH9K_MODE_11NA_HT40PLUS;
	else if (chan->chanmode == CHANNEL_A_HT40MINUS)
		return WIRELESS_MODE_11NA_HT40MINUS;
		return ATH9K_MODE_11NA_HT40MINUS;
	else if (chan->chanmode == CHANNEL_G_HT40PLUS)
		return WIRELESS_MODE_11NG_HT40PLUS;
		return ATH9K_MODE_11NG_HT40PLUS;
	else if (chan->chanmode == CHANNEL_G_HT40MINUS)
		return WIRELESS_MODE_11NG_HT40MINUS;
		return ATH9K_MODE_11NG_HT40MINUS;

	/* NB: should not get here */
	return WIRELESS_MODE_11b;
}

/*
 *  Change Channels
 *
 *  Performs the actions to change the channel in the hardware, and set up
 *  the current operating mode for the new channel.
*/

static void ath_chan_change(struct ath_softc *sc, struct ath9k_channel *chan)
{
	enum wireless_mode mode;

	mode = ath_chan2mode(chan);

	ath_rate_setup(sc, mode);
	ath_setcurmode(sc, mode);
	return ATH9K_MODE_11B;
}

/*
@@ -480,7 +438,8 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
		 * Change channels and update the h/w rate map
		 * if we're switching; e.g. 11a to 11b/g.
		 */
		ath_chan_change(sc, hchan);
		ath_setcurmode(sc, ath_chan2mode(hchan));

		ath_update_txpow(sc);	/* update tx power state */
		/*
		 * Re-enable interrupts.
@@ -860,7 +819,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
	 *  vap and node data structures, which will be needed as soon
	 *  as we start receiving.
	 */
	ath_chan_change(sc, initial_chan);
	ath_setcurmode(sc, ath_chan2mode(initial_chan));

	/* XXX: we must make sure h/w is ready and clear invalid flag
	 * before turning on interrupt. */
@@ -902,7 +861,7 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag)
	 * that changes the channel so update any state that
	 * might change as a result.
	 */
	ath_chan_change(sc, &sc->sc_curchan);
	ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan));

	ath_update_txpow(sc);	/* update tx power state */

@@ -1212,14 +1171,13 @@ int ath_init(u16 devid, struct ath_softc *sc)
	/* default to STA mode */
	sc->sc_opmode = ATH9K_M_MONITOR;

	/* Setup rate tables for all potential media types. */
	/* 11g encompasses b,g */
	/* Setup rate tables */

	ath_rate_setup(sc, WIRELESS_MODE_11a);
	ath_rate_setup(sc, WIRELESS_MODE_11g);
	ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
	ath_setup_rates(sc, IEEE80211_BAND_5GHZ);

	/* NB: setup here so ath_rate_update is happy */
	ath_setcurmode(sc, WIRELESS_MODE_11a);
	ath_setcurmode(sc, ATH9K_MODE_11A);

	/*
	 * Allocate hardware transmit queues: one queue for
+0 −2
Original line number Diff line number Diff line
@@ -1004,10 +1004,8 @@ struct ath_softc {

	/* Rate */
	struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
	const struct ath9k_rate_table *sc_rates[WIRELESS_MODE_MAX];
	const struct ath9k_rate_table *sc_currates;
	u8 sc_rixmap[256];	/* IEEE to h/w rate table ix */
	u8 sc_minrateix;	/* min h/w rate index */
	u8 sc_protrix;		/* protection rate index */
	struct {
		u32 rateKbps;	/* transfer rate in kbs */
+45 −34
Original line number Diff line number Diff line
@@ -225,10 +225,10 @@ static enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
				       const struct ath9k_channel *chan)
{
	if (IS_CHAN_CCK(chan))
		return WIRELESS_MODE_11b;
		return ATH9K_MODE_11A;
	if (IS_CHAN_G(chan))
		return WIRELESS_MODE_11g;
	return WIRELESS_MODE_11a;
		return ATH9K_MODE_11G;
	return ATH9K_MODE_11A;
}

static bool ath9k_hw_wait(struct ath_hal *ah,
@@ -2416,7 +2416,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
		return;
	} else {
		mode = ath9k_hw_chan2wmode(ah, chan);
		if (mode == WIRELESS_MODE_11g || mode == WIRELESS_MODE_11b) {
		if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
			if (!aniState->ofdmWeakSigDetectOff)
				ath9k_hw_ani_control(ah,
				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
@@ -2462,7 +2462,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
					     aniState->firstepLevel + 1);
	} else {
		mode = ath9k_hw_chan2wmode(ah, chan);
		if (mode == WIRELESS_MODE_11g || mode == WIRELESS_MODE_11b) {
		if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
			if (aniState->firstepLevel > 0)
				ath9k_hw_ani_control(ah,
						     ATH9K_ANI_FIRSTEP_LEVEL,
@@ -2970,29 +2970,40 @@ static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
			 ah->ah_currentRD);
	}

	pCap->wireless_modes = 0;
	eeval = ath9k_hw_get_eeprom(ahp, EEP_OP_MODE);
	bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);

	if (eeval & AR5416_OPFLAGS_11A) {
		pCap->wireless_modes |= ATH9K_MODE_SEL_11A |
			((!ah->ah_config.ht_enable
			  || (eeval & AR5416_OPFLAGS_N_5G_HT20)) ? 0
			 : (ATH9K_MODE_SEL_11NA_HT20 |
			    ((eeval & AR5416_OPFLAGS_N_5G_HT40) ? 0
			     : (ATH9K_MODE_SEL_11NA_HT40PLUS |
				ATH9K_MODE_SEL_11NA_HT40MINUS))));
		set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
		if (ah->ah_config.ht_enable) {
			if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
				set_bit(ATH9K_MODE_11NA_HT20,
					pCap->wireless_modes);
			if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
				set_bit(ATH9K_MODE_11NA_HT40PLUS,
					pCap->wireless_modes);
				set_bit(ATH9K_MODE_11NA_HT40MINUS,
					pCap->wireless_modes);
			}
		}
	}
	if (eeval & AR5416_OPFLAGS_11G) {
		pCap->wireless_modes |=
			ATH9K_MODE_SEL_11B | ATH9K_MODE_SEL_11G |
			((!ah->ah_config.ht_enable
			  || (eeval & AR5416_OPFLAGS_N_2G_HT20)) ? 0
			 : (ATH9K_MODE_SEL_11NG_HT20 |
			    ((eeval & AR5416_OPFLAGS_N_2G_HT40) ? 0
			     : (ATH9K_MODE_SEL_11NG_HT40PLUS |
				ATH9K_MODE_SEL_11NG_HT40MINUS))));

	if (eeval & AR5416_OPFLAGS_11G) {
		set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
		set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
		if (ah->ah_config.ht_enable) {
			if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
				set_bit(ATH9K_MODE_11NG_HT20,
					pCap->wireless_modes);
			if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
				set_bit(ATH9K_MODE_11NG_HT40PLUS,
					pCap->wireless_modes);
				set_bit(ATH9K_MODE_11NG_HT40MINUS,
					pCap->wireless_modes);
			}
		}
	}

	pCap->tx_chainmask = ath9k_hw_get_eeprom(ahp, EEP_TX_MASK);
	if ((ah->ah_isPciExpress)
	    || (eeval & AR5416_OPFLAGS_11A)) {
@@ -5213,7 +5224,7 @@ static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks)
		return clks /
		CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)];
	else
		return clks / CLOCK_RATE[WIRELESS_MODE_11b];
		return clks / CLOCK_RATE[ATH9K_MODE_11B];
}

static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks)
@@ -5232,7 +5243,7 @@ static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs)
		return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
			ah->ah_curchan)];
	else
		return usecs * CLOCK_RATE[WIRELESS_MODE_11b];
		return usecs * CLOCK_RATE[ATH9K_MODE_11B];
}

static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
@@ -5924,7 +5935,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
			    AR_GPIO_JTAG_DISABLE);

		if (ah->ah_caps.wireless_modes & ATH9K_MODE_SEL_11A) {
		if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes)) {
			if (IS_CHAN_5GHZ(chan))
				ath9k_hw_set_gpio(ah, 9, 0);
			else
@@ -8238,23 +8249,23 @@ const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
{
	struct ath9k_rate_table *rt;
	switch (mode) {
	case ATH9K_MODE_SEL_11A:
	case ATH9K_MODE_11A:
		rt = &ar5416_11a_table;
		break;
	case ATH9K_MODE_SEL_11B:
	case ATH9K_MODE_11B:
		rt = &ar5416_11b_table;
		break;
	case ATH9K_MODE_SEL_11G:
	case ATH9K_MODE_11G:
		rt = &ar5416_11g_table;
		break;
	case ATH9K_MODE_SEL_11NG_HT20:
	case ATH9K_MODE_SEL_11NG_HT40PLUS:
	case ATH9K_MODE_SEL_11NG_HT40MINUS:
	case ATH9K_MODE_11NG_HT20:
	case ATH9K_MODE_11NG_HT40PLUS:
	case ATH9K_MODE_11NG_HT40MINUS:
		rt = &ar5416_11ng_table;
		break;
	case ATH9K_MODE_SEL_11NA_HT20:
	case ATH9K_MODE_SEL_11NA_HT40PLUS:
	case ATH9K_MODE_SEL_11NA_HT40MINUS:
	case ATH9K_MODE_11NA_HT20:
	case ATH9K_MODE_11NA_HT40PLUS:
	case ATH9K_MODE_11NA_HT40MINUS:
		rt = &ar5416_11na_table;
		break;
	default:
Loading