Commit 63266a65 authored by Bruno Randolf's avatar Bruno Randolf Committed by John W. Linville

ath5k: rates cleanup

cleanup the rates structures used by ath5k. instead of separate driver and
mac80211 rate structures we now setup a static ieee80211_rate array and use it
directly. no conversion between two different rate structures has to be done
any more. a lot of unused and confusing junk was deleted.

renamed ath5k_getchannels into ath5k_setup_bands because this is what it does.
rewrote it to copy the bitrates correctly for each band. this is necessary for
running different hardware with the same driver (e.g. 5211 and 5212 based
cards).

add special handling of rates for AR5211 chipsets: it uses different rate codes
for CCK rates (which are actually like the other chips but with a 0xF mask).

setup a hardware code to rate index reverse mapping table for getting the rate
index of received frames.

the rates for control frames which have to be set in
ath5k_hw_write_rate_duration are now in one single array.

drivers/net/wireless/ath5k/ath5k.h:     Changes-licensed-under: ISC
drivers/net/wireless/ath5k/base.c:      Changes-licensed-under: 3-Clause-BSD
drivers/net/wireless/ath5k/base.h:      Changes-licensed-under: 3-Clause-BSD
drivers/net/wireless/ath5k/hw.c:        Changes-licensed-under: ISC
Signed-off-by: default avatarBruno Randolf <br1@einfach.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 92ab8535
...@@ -271,11 +271,6 @@ enum ath5k_driver_mode { ...@@ -271,11 +271,6 @@ enum ath5k_driver_mode {
/* adding this flag to rate_code enables short preamble, see ar5212_reg.h */ /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
#define AR5K_SET_SHORT_PREAMBLE 0x04 #define AR5K_SET_SHORT_PREAMBLE 0x04
#define HAS_SHPREAMBLE(_ix) \
(rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
#define SHPREAMBLE_FLAG(_ix) \
(HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
/****************\ /****************\
TX DEFINITIONS TX DEFINITIONS
...@@ -568,152 +563,61 @@ struct ath5k_athchan_2ghz { ...@@ -568,152 +563,61 @@ struct ath5k_athchan_2ghz {
u16 a2_athchan; u16 a2_athchan;
}; };
/* /*
* Rate definitions * Rate definitions
* TODO: Clean them up or move them on mac80211 -most of these infos are
* used by the rate control algorytm on MadWiFi.
*/ */
/* Max number of rates on the rate table and what it seems
* Atheros hardware supports */
#define AR5K_MAX_RATES 32
/** /**
* struct ath5k_rate - rate structure * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
* @valid: is this a valid rate for rate control (remove)
* @modulation: respective mac80211 modulation
* @rate_kbps: rate in kbit/s
* @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
* &struct ath5k_rx_status.rs_rate and on TX on
* &struct ath5k_tx_status.ts_rate. Seems the ar5xxx harware supports
* up to 32 rates, indexed by 1-32. This means we really only need
* 6 bits for the rate_code.
* @dot11_rate: respective IEEE-802.11 rate value
* @control_rate: index of rate assumed to be used to send control frames.
* This can be used to set override the value on the rate duration
* registers. This is only useful if we can override in the harware at
* what rate we want to send control frames at. Note that IEEE-802.11
* Ch. 9.6 (after IEEE 802.11g changes) defines the rate at which we
* should send ACK/CTS, if we change this value we can be breaking
* the spec.
* *
* This structure is used to get the RX rate or set the TX rate on the * The rate code is used to get the RX rate or set the TX rate on the
* hardware descriptors. It is also used for internal modulation control * hardware descriptors. It is also used for internal modulation control
* and settings. * and settings.
* *
* On RX after the &struct ath5k_desc is parsed by the appropriate * This is the hardware rate map we are aware of:
* ah_proc_rx_desc() the respective hardware rate value is set in
* &struct ath5k_rx_status.rs_rate. On TX the desired rate is set in
* &struct ath5k_tx_status.ts_rate which is later used to setup the
* &struct ath5k_desc correctly. This is the hardware rate map we are
* aware of:
* *
* rate_code 1 2 3 4 5 6 7 8 * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
* rate_kbps 3000 1000 ? ? ? 2000 500 48000 * rate_kbps 3000 1000 ? ? ? 2000 500 48000
* *
* rate_code 9 10 11 12 13 14 15 16 * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10
* rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
* *
* rate_code 17 18 19 20 21 22 23 24 * rate_code 17 18 19 20 21 22 23 24
* rate_kbps ? ? ? ? ? ? ? 11000 * rate_kbps ? ? ? ? ? ? ? 11000
* *
* rate_code 25 26 27 28 29 30 31 32 * rate_code 25 26 27 28 29 30 31 32
* rate_kbps 5500 2000 1000 ? ? ? ? ? * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ?
* *
* "S" indicates CCK rates with short preamble.
*
* AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
* lowest 4 bits, so they are the same as below with a 0xF mask.
* (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
* We handle this in ath5k_setup_bands().
*/ */
struct ath5k_rate { #define AR5K_MAX_RATES 32
u8 valid;
u32 modulation;
u16 rate_kbps;
u8 rate_code;
u8 dot11_rate;
u8 control_rate;
};
/* XXX: GRR all this stuff to get leds blinking ??? (check out setcurmode) */
struct ath5k_rate_table {
u16 rate_count;
u8 rate_code_to_index[AR5K_MAX_RATES]; /* Back-mapping */
struct ath5k_rate rates[AR5K_MAX_RATES];
};
/*
* Rate tables...
* TODO: CLEAN THIS !!!
*/
#define AR5K_RATES_11A { 8, { \
255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
255, 255, 255, 255, 255, 255, 255, 255 }, { \
{ 1, 0, 6000, 11, 140, 0 }, \
{ 1, 0, 9000, 15, 18, 0 }, \
{ 1, 0, 12000, 10, 152, 2 }, \
{ 1, 0, 18000, 14, 36, 2 }, \
{ 1, 0, 24000, 9, 176, 4 }, \
{ 1, 0, 36000, 13, 72, 4 }, \
{ 1, 0, 48000, 8, 96, 4 }, \
{ 1, 0, 54000, 12, 108, 4 } } \
}
#define AR5K_RATES_11B { 4, { \
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
3, 2, 1, 0, 255, 255, 255, 255 }, { \
{ 1, 0, 1000, 27, 130, 0 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } } \
}
#define AR5K_RATES_11G { 12, { \
255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
3, 2, 1, 0, 255, 255, 255, 255 }, { \
{ 1, 0, 1000, 27, 2, 0 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 }, \
{ 0, 0, 6000, 11, 12, 4 }, \
{ 0, 0, 9000, 15, 18, 4 }, \
{ 1, 0, 12000, 10, 24, 6 }, \
{ 1, 0, 18000, 14, 36, 6 }, \
{ 1, 0, 24000, 9, 48, 8 }, \
{ 1, 0, 36000, 13, 72, 8 }, \
{ 1, 0, 48000, 8, 96, 8 }, \
{ 1, 0, 54000, 12, 108, 8 } } \
}
#define AR5K_RATES_TURBO { 8, { \ /* B */
255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \ #define ATH5K_RATE_CODE_1M 0x1B
7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \ #define ATH5K_RATE_CODE_2M 0x1A
255, 255, 255, 255, 255, 255, 255, 255 }, { \ #define ATH5K_RATE_CODE_5_5M 0x19
{ 1, MODULATION_TURBO, 6000, 11, 140, 0 }, \ #define ATH5K_RATE_CODE_11M 0x18
{ 1, MODULATION_TURBO, 9000, 15, 18, 0 }, \ /* A and G */
{ 1, MODULATION_TURBO, 12000, 10, 152, 2 }, \ #define ATH5K_RATE_CODE_6M 0x0B
{ 1, MODULATION_TURBO, 18000, 14, 36, 2 }, \ #define ATH5K_RATE_CODE_9M 0x0F
{ 1, MODULATION_TURBO, 24000, 9, 176, 4 }, \ #define ATH5K_RATE_CODE_12M 0x0A
{ 1, MODULATION_TURBO, 36000, 13, 72, 4 }, \ #define ATH5K_RATE_CODE_18M 0x0E
{ 1, MODULATION_TURBO, 48000, 8, 96, 4 }, \ #define ATH5K_RATE_CODE_24M 0x09
{ 1, MODULATION_TURBO, 54000, 12, 108, 4 } } \ #define ATH5K_RATE_CODE_36M 0x0D
} #define ATH5K_RATE_CODE_48M 0x08
#define ATH5K_RATE_CODE_54M 0x0C
/* XR */
#define ATH5K_RATE_CODE_XR_500K 0x07
#define ATH5K_RATE_CODE_XR_1M 0x02
#define ATH5K_RATE_CODE_XR_2M 0x06
#define ATH5K_RATE_CODE_XR_3M 0x01
#define AR5K_RATES_XR { 12, { \
255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4, \
11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
255, 255, 255, 255, 255, 255, 255, 255 }, { \
{ 1, MODULATION_XR, 500, 7, 129, 0 }, \
{ 1, MODULATION_XR, 1000, 2, 139, 1 }, \
{ 1, MODULATION_XR, 2000, 6, 150, 2 }, \
{ 1, MODULATION_XR, 3000, 1, 150, 3 }, \
{ 1, 0, 6000, 11, 140, 4 }, \
{ 1, 0, 9000, 15, 18, 4 }, \
{ 1, 0, 12000, 10, 152, 6 }, \
{ 1, 0, 18000, 14, 36, 6 }, \
{ 1, 0, 24000, 9, 176, 8 }, \
{ 1, 0, 36000, 13, 72, 8 }, \
{ 1, 0, 48000, 8, 96, 8 }, \
{ 1, 0, 54000, 12, 108, 8 } } \
}
/* /*
* Crypto definitions * Crypto definitions
......
This diff is collapsed.
...@@ -111,17 +111,13 @@ struct ath5k_softc { ...@@ -111,17 +111,13 @@ struct ath5k_softc {
struct ieee80211_hw *hw; /* IEEE 802.11 common */ struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ieee80211_channel channels[ATH_CHAN_MAX]; struct ieee80211_channel channels[ATH_CHAN_MAX];
struct ieee80211_rate rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS]; struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
u8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
enum ieee80211_if_types opmode; enum ieee80211_if_types opmode;
struct ath5k_hw *ah; /* Atheros HW */ struct ath5k_hw *ah; /* Atheros HW */
struct ieee80211_supported_band *curband; struct ieee80211_supported_band *curband;
u8 a_rates;
u8 b_rates;
u8 g_rates;
u8 xr_rates;
#ifdef CONFIG_ATH5K_DEBUG #ifdef CONFIG_ATH5K_DEBUG
struct ath5k_dbg_info debug; /* debug info */ struct ath5k_dbg_info debug; /* debug info */
#endif /* CONFIG_ATH5K_DEBUG */ #endif /* CONFIG_ATH5K_DEBUG */
......
...@@ -31,13 +31,6 @@ ...@@ -31,13 +31,6 @@
#include "base.h" #include "base.h"
#include "debug.h" #include "debug.h"
/* Rate tables */
static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A;
static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B;
static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G;
static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO;
static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR;
/* Prototypes */ /* Prototypes */
static int ath5k_hw_nic_reset(struct ath5k_hw *, u32); static int ath5k_hw_nic_reset(struct ath5k_hw *, u32);
static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool); static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool);
...@@ -520,34 +513,6 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ...@@ -520,34 +513,6 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return 0; return 0;
} }
/*
* Get the rate table for a specific operation mode
*/
const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
unsigned int mode)
{
ATH5K_TRACE(ah->ah_sc);
if (!test_bit(mode, ah->ah_capabilities.cap_mode))
return NULL;
/* Get rate tables */
switch (mode) {
case AR5K_MODE_11A:
return &ath5k_rt_11a;
case AR5K_MODE_11A_TURBO:
return &ath5k_rt_turbo;
case AR5K_MODE_11B:
return &ath5k_rt_11b;
case AR5K_MODE_11G:
return &ath5k_rt_11g;
case AR5K_MODE_11G_TURBO:
return &ath5k_rt_xr;
}
return NULL;
}
/* /*
* Free the ath5k_hw struct * Free the ath5k_hw struct
*/ */
...@@ -618,45 +583,42 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, ...@@ -618,45 +583,42 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
return 0; return 0;
} }
/*
* index into rates for control rates, we can set it up like this because
* this is only used for AR5212 and we know it supports G mode
*/
static int control_rates[] =
{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
/** /**
* ath5k_hw_write_rate_duration - set rate duration during hw resets * ath5k_hw_write_rate_duration - set rate duration during hw resets
* *
* @ah: the &struct ath5k_hw * @ah: the &struct ath5k_hw
* @mode: one of enum ath5k_driver_mode * @mode: one of enum ath5k_driver_mode
* *
* Write the rate duration table for the current mode upon hw reset. This * Write the rate duration table upon hw reset. This is a helper for
* is a helper for ath5k_hw_reset(). It seems all this is doing is setting * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout for
* an ACK timeout for the hardware for the current mode for each rate. The * the hardware for the current mode for each rate. The rates which are capable
* rates which are capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another
* and 11Mbps) have another register for the short preamble ACK timeout * register for the short preamble ACK timeout calculation.
* calculation.
*
*/ */
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
unsigned int mode) unsigned int mode)
{ {
struct ath5k_softc *sc = ah->ah_sc; struct ath5k_softc *sc = ah->ah_sc;
const struct ath5k_rate_table *rt; struct ieee80211_rate *rate;
struct ieee80211_rate srate = {};
unsigned int i; unsigned int i;
/* Get rate table for the current operating mode */
rt = ath5k_hw_get_rate_table(ah, mode);
/* Write rate duration table */ /* Write rate duration table */
for (i = 0; i < rt->rate_count; i++) { for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
const struct ath5k_rate *rate, *control_rate;
u32 reg; u32 reg;
u16 tx_time; u16 tx_time;
rate = &rt->rates[i]; rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
control_rate = &rt->rates[rate->control_rate];
/* Set ACK timeout */ /* Set ACK timeout */
reg = AR5K_RATE_DUR(rate->rate_code); reg = AR5K_RATE_DUR(rate->hw_value);
srate.bitrate = control_rate->rate_kbps/100;
/* An ACK frame consists of 10 bytes. If you add the FCS, /* An ACK frame consists of 10 bytes. If you add the FCS,
* which ieee80211_generic_frame_duration() adds, * which ieee80211_generic_frame_duration() adds,
...@@ -665,11 +627,11 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, ...@@ -665,11 +627,11 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
* ieee80211_duration() for a brief description of * ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */ * what rate we should choose to TX ACKs. */
tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
sc->vif, 10, &srate)); sc->vif, 10, rate));
ath5k_hw_reg_write(ah, tx_time, reg); ath5k_hw_reg_write(ah, tx_time, reg);
if (!HAS_SHPREAMBLE(i)) if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
continue; continue;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment