Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 224871
b: refs/heads/master
c: 61cde03
h: refs/heads/master
i:
  224869: e6f7beb
  224867: e316412
  224863: aba24c3
v: v3
  • Loading branch information
Nick Kossifidis authored and John W. Linville committed Nov 30, 2010
1 parent a82c0a9 commit 101c494
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 47 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3017fcab416d8d1ee48ca16aa9a3062f600dab8e
refs/heads/master: 61cde037234c4b8e6497a23f5f236c64cbf9d41d
12 changes: 10 additions & 2 deletions trunk/drivers/net/wireless/ath/ath5k/ath5k.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@
#define AR5K_INIT_SIFS_HALF_RATE 32
#define AR5K_INIT_SIFS_QUARTER_RATE 64

/* Used to calculate tx time for non 5/10/40MHz
* operation */
/* It's preamble time + signal time (16 + 4) */
#define AR5K_INIT_OFDM_PREAMPLE_TIME 20
/* Preamble time for 40MHz (turbo) operation (min ?) */
#define AR5K_INIT_OFDM_PREAMBLE_TIME_MIN 14
#define AR5K_INIT_OFDM_SYMBOL_TIME 4
#define AR5K_INIT_OFDM_PLCP_BITS 22

/* Rx latency for 5 and 10MHz operation (max ?) */
#define AR5K_INIT_RX_LAT_MAX 63
/* Tx latencies from initvals (5212 only but no problem
Expand Down Expand Up @@ -1083,6 +1092,7 @@ struct ath5k_hw {

u32 ah_limit_tx_retries;
u8 ah_coverage_class;
bool ah_ack_bitrate_high;
u8 ah_bwmode;

/* Antenna Control */
Expand Down Expand Up @@ -1248,8 +1258,6 @@ void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
/* ACK bit rate */
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
/* Init function */
void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
u8 mode);
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/net/wireless/ath/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2420,7 +2420,9 @@ ath5k_init(struct ath5k_softc *sc)
for (i = 0; i < common->keymax; i++)
ath_hw_keyreset(common, (u16) i);

ath5k_hw_set_ack_bitrate_high(ah, true);
/* Use higher rates for acks instead of base
* rate */
ah->ah_ack_bitrate_high = true;

for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
sc->bslot[i] = NULL;
Expand Down
159 changes: 116 additions & 43 deletions trunk/drivers/net/wireless/ath/ath5k/pcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,99 @@
#include "debug.h"
#include "base.h"

/*
* AR5212+ can use higher rates for ack transmition
* based on current tx rate instead of the base rate.
* It does this to better utilize channel usage.
* This is a mapping between G rates (that cover both
* CCK and OFDM) and ack rates that we use when setting
* rate -> duration table. This mapping is hw-based so
* don't change anything.
*
* To enable this functionality we must set
* ah->ah_ack_bitrate_high to true else base rate is
* used (1Mb for CCK, 6Mb for OFDM).
*/
static const unsigned int ack_rates_high[] =
/* Tx -> ACK */
/* 1Mb -> 1Mb */ { 0,
/* 2MB -> 2Mb */ 1,
/* 5.5Mb -> 2Mb */ 1,
/* 11Mb -> 2Mb */ 1,
/* 6Mb -> 6Mb */ 4,
/* 9Mb -> 6Mb */ 4,
/* 12Mb -> 12Mb */ 6,
/* 18Mb -> 12Mb */ 6,
/* 24Mb -> 24Mb */ 8,
/* 36Mb -> 24Mb */ 8,
/* 48Mb -> 24Mb */ 8,
/* 54Mb -> 24Mb */ 8 };

/*******************\
* Helper functions *
\*******************/

/**
* ath5k_hw_get_frame_duration - Get tx time of a frame
*
* @ah: The &struct ath5k_hw
* @len: Frame's length in bytes
* @rate: The @struct ieee80211_rate
*
* Calculate tx duration of a frame given it's rate and length
* It extends ieee80211_generic_frame_duration for non standard
* bwmodes.
*/
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate)
{
struct ath5k_softc *sc = ah->ah_sc;
int sifs, preamble, plcp_bits, sym_time;
int bitrate, bits, symbols, symbol_bits;
int dur;

/* Fallback */
if (!ah->ah_bwmode) {
dur = ieee80211_generic_frame_duration(sc->hw,
NULL, len, rate);
return dur;
}

bitrate = rate->bitrate;
preamble = AR5K_INIT_OFDM_PREAMPLE_TIME;
plcp_bits = AR5K_INIT_OFDM_PLCP_BITS;
sym_time = AR5K_INIT_OFDM_SYMBOL_TIME;

switch (ah->ah_bwmode) {
case AR5K_BWMODE_40MHZ:
sifs = AR5K_INIT_SIFS_TURBO;
preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN;
break;
case AR5K_BWMODE_10MHZ:
sifs = AR5K_INIT_SIFS_HALF_RATE;
preamble *= 2;
sym_time *= 2;
break;
case AR5K_BWMODE_5MHZ:
sifs = AR5K_INIT_SIFS_QUARTER_RATE;
preamble *= 4;
sym_time *= 4;
break;
default:
sifs = AR5K_INIT_SIFS_DEFAULT_BG;
break;
}

bits = plcp_bits + (len << 3);
/* Bit rate is in 100Kbits */
symbol_bits = bitrate * sym_time;
symbols = DIV_ROUND_UP(bits * 10, symbol_bits);

dur = sifs + preamble + (sym_time * symbols);

return dur;
}

/**
* ath5k_hw_get_default_slottime - Get the default slot time for current mode
*
Expand Down Expand Up @@ -120,75 +209,50 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
}

/**
* ath5k_hw_set_ack_bitrate - set bitrate for ACKs
*
* @ah: The &struct ath5k_hw
* @high: Flag to determine if we want to use high transmission rate
* for ACKs or not
*
* If high flag is set, we tell hw to use a set of control rates based on
* the current transmission rate (check out control_rates array inside reset.c).
* If not hw just uses the lowest rate available for the current modulation
* scheme being used (1Mbit for CCK and 6Mbits for OFDM).
*/
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
{
if (ah->ah_version != AR5K_AR5212)
return;
else {
u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
if (high)
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
else
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
}
}


/******************\
* ACK/CTS Timeouts *
\******************/

/*
* 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 const unsigned int control_rates[] =
{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };

/**
* ath5k_hw_write_rate_duration - fill rate code to duration table
*
* @ah: the &struct ath5k_hw
* @mode: one of enum ath5k_driver_mode
*
* Write the rate code to duration table upon hw reset. This is a helper for
* ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
* ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on
* the hardware, based on current mode, for each rate. The rates which are
* capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
* different rate code so we write their value twice (one for long preamble
* and one for short).
*
* Note: Band doesn't matter here, if we set the values for OFDM it works
* on both a and g modes. So all we have to do is set values for all g rates
* that include all OFDM and CCK rates. If we operate in turbo or xr/half/
* quarter rate mode, we need to use another set of bitrates (that's why we
* need the mode parameter) but we don't handle these proprietary modes yet.
* that include all OFDM and CCK rates.
*
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
unsigned int mode)
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
{
struct ath5k_softc *sc = ah->ah_sc;
struct ieee80211_rate *rate;
unsigned int i;
/* 802.11g covers both OFDM and CCK */
u8 band = IEEE80211_BAND_2GHZ;

/* Write rate duration table */
for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
u32 reg;
u16 tx_time;

rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
if (ah->ah_ack_bitrate_high)
rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
/* CCK -> 1Mb */
else if (i < 4)
rate = &sc->sbands[band].bitrates[0];
/* OFDM -> 6Mb */
else
rate = &sc->sbands[band].bitrates[4];

/* Set ACK timeout */
reg = AR5K_RATE_DUR(rate->hw_value);
Expand All @@ -199,8 +263,9 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
* actual rate for this rate. See mac80211 tx.c
* ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */
tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
NULL, 10, rate));
tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);

tx_time = le16_to_cpu(tx_time);

ath5k_hw_reg_write(ah, tx_time, reg);

Expand Down Expand Up @@ -835,7 +900,7 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
ah->ah_sc->nvifs)
ath5k_hw_write_rate_duration(ah, mode);
ath5k_hw_write_rate_duration(ah);

/* Set RSSI/BRSSI thresholds
*
Expand Down Expand Up @@ -869,5 +934,13 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
if (ah->ah_coverage_class > 0)
ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);

/* Set ACK bitrate mode (see ack_rates_high) */
if (ah->ah_version == AR5K_AR5212) {
u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
if (ah->ah_ack_bitrate_high)
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
else
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
}
return;
}

0 comments on commit 101c494

Please sign in to comment.