ath5k: Reimplement clock rate to usec conversion

The original code was correct in 802.11a mode only, 802.11b/g uses
different clock rates. The new code uses values taken from FreeBSD HAL
and should be correct for all modes including turbo modes.

The former rate calculation was used by slope coefficient calculation
function ath5k_hw_write_ofdm_timings. However, this function requires
the 802.11a values even in 802.11g mode. Thus the use of
ath5k_hw_htoclock was replaced by hardcoded values. Possibly the slope
coefficient calculation is not related to clock rate at all.

Signed-off-by: Lukas Turek <8an@praha12.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Lukáš Turek 2009-12-21 22:50:50 +01:00 committed by John W. Linville
parent e1aa369ec8
commit 3578e6ebb3
4 changed files with 62 additions and 33 deletions

View file

@ -1231,6 +1231,10 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
/* Clock rate related functions */
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
/* Key table (WEP) functions */
extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
@ -1310,24 +1314,6 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
* Functions used internaly
*/
/*
* Translate usec to hw clock units
* TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
{
return turbo ? (usec * 80) : (usec * 40);
}
/*
* Translate hw clock units to usec
* TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
{
return turbo ? (clock / 80) : (clock / 40);
}
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
{
return &ah->common;

View file

@ -187,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);
return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_ACK));
}
/**
@ -200,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
{
ATH5K_TRACE(ah->ah_sc);
if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
ah->ah_turbo) <= timeout)
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
<= timeout)
return -EINVAL;
AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
ath5k_hw_htoclock(timeout, ah->ah_turbo));
ath5k_hw_htoclock(ah, timeout));
return 0;
}
@ -218,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);
return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_CTS));
}
/**
@ -231,16 +231,60 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
{
ATH5K_TRACE(ah->ah_sc);
if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
ah->ah_turbo) <= timeout)
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
<= timeout)
return -EINVAL;
AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
ath5k_hw_htoclock(timeout, ah->ah_turbo));
ath5k_hw_htoclock(ah, timeout));
return 0;
}
/**
* ath5k_hw_htoclock - Translate usec to hw clock units
*
* @ah: The &struct ath5k_hw
* @usec: value in microseconds
*/
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
{
return usec * ath5k_hw_get_clockrate(ah);
}
/**
* ath5k_hw_clocktoh - Translate hw clock units to usec
* @clock: value in hw clock units
*/
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
{
return clock / ath5k_hw_get_clockrate(ah);
}
/**
* ath5k_hw_get_clockrate - Get the clock rate for current mode
*
* @ah: The &struct ath5k_hw
*/
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
{
struct ieee80211_channel *channel = ah->ah_current_channel;
int clock;
if (channel->hw_value & CHANNEL_5GHZ)
clock = 40; /* 802.11a */
else if (channel->hw_value & CHANNEL_CCK)
clock = 22; /* 802.11b */
else
clock = 44; /* 802.11g */
/* Clock rate in turbo modes is twice the normal rate */
if (channel->hw_value & CHANNEL_TURBO)
clock *= 2;
return clock;
}
/**
* ath5k_hw_set_lladdr - Set station id
*

View file

@ -529,7 +529,7 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
else
slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT);
return ath5k_hw_clocktoh(slot_time_clock & 0xffff, ah->ah_turbo);
return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff);
}
/*
@ -537,7 +537,7 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
*/
int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
{
u32 slot_time_clock = ath5k_hw_htoclock(slot_time, ah->ah_turbo);
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
ATH5K_TRACE(ah->ah_sc);

View file

@ -60,12 +60,11 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
!(channel->hw_value & CHANNEL_OFDM));
/* Get coefficient
* ALGO: coef = (5 * clock * carrier_freq) / 2)
* ALGO: coef = (5 * clock / carrier_freq) / 2
* we scale coef by shifting clock value by 24 for
* better precision since we use integers */
/* TODO: Half/quarter rate */
clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40;
coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
/* Get exponent