Skip to content

Commit

Permalink
ath9k: Revamp wireless mode usage
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sujith authored and John W. Linville committed Aug 7, 2008
1 parent 3b95978 commit 86b89ee
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 324 deletions.
48 changes: 15 additions & 33 deletions drivers/net/wireless/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath9k/beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
150 changes: 54 additions & 96 deletions drivers/net/wireless/ath9k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand Down Expand Up @@ -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.
*/

static int ath_rate_setup(struct ath_softc *sc, enum wireless_mode mode)
* Set up rate table (legacy rates)
*/
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);
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_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);
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;

/* setup rate set in 802.11 protocol layer */
ath_setup_rate(sc, mode, NORMAL_RATE, rt);
if (rt == NULL)
return;

return 1;
sband = &sc->sbands[band];
rate = sc->rates[band];

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);
}
}

/*
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

/*
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/wireless/ath9k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit 86b89ee

Please sign in to comment.