ath5k: Simplify cw_min/max and AIFS configuration
Get rid of overly complicated cw_min/max and AIFS configuration: * Validate values in ath5k_hw_set_tx_queueprops(), so we can use them directly without further checks or computation in ath5k_hw_reset_tx_queue(). * Simplifiy by using AR5K_TUNE_AIFS|CWMIN|CWMAX variables directly since we don't support XR or B channels. That way we can also remove AR5K_TXQ_USEDEFAULT and the confusing logic around it. * Update data types: AIFS is u8, CW's are u16. * Remove now unneeded variables in ath5k_hw. Signed-off-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
234132960d
commit
de8af45520
@@ -258,8 +258,6 @@
|
|||||||
(AR5K_INIT_PROG_IFS_TURBO) \
|
(AR5K_INIT_PROG_IFS_TURBO) \
|
||||||
)
|
)
|
||||||
|
|
||||||
/* token to use for aifs, cwmin, cwmax in MadWiFi */
|
|
||||||
#define AR5K_TXQ_USEDEFAULT ((u32) -1)
|
|
||||||
|
|
||||||
/* GENERIC CHIPSET DEFINITIONS */
|
/* GENERIC CHIPSET DEFINITIONS */
|
||||||
|
|
||||||
@@ -530,9 +528,9 @@ struct ath5k_txq_info {
|
|||||||
enum ath5k_tx_queue tqi_type;
|
enum ath5k_tx_queue tqi_type;
|
||||||
enum ath5k_tx_queue_subtype tqi_subtype;
|
enum ath5k_tx_queue_subtype tqi_subtype;
|
||||||
u16 tqi_flags; /* Tx queue flags (see above) */
|
u16 tqi_flags; /* Tx queue flags (see above) */
|
||||||
u32 tqi_aifs; /* Arbitrated Interframe Space */
|
u8 tqi_aifs; /* Arbitrated Interframe Space */
|
||||||
s32 tqi_cw_min; /* Minimum Contention Window */
|
u16 tqi_cw_min; /* Minimum Contention Window */
|
||||||
s32 tqi_cw_max; /* Maximum Contention Window */
|
u16 tqi_cw_max; /* Maximum Contention Window */
|
||||||
u32 tqi_cbr_period; /* Constant bit rate period */
|
u32 tqi_cbr_period; /* Constant bit rate period */
|
||||||
u32 tqi_cbr_overflow_limit;
|
u32 tqi_cbr_overflow_limit;
|
||||||
u32 tqi_burst_time;
|
u32 tqi_burst_time;
|
||||||
@@ -1044,9 +1042,6 @@ struct ath5k_hw {
|
|||||||
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
|
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
|
||||||
|
|
||||||
u32 ah_atim_window;
|
u32 ah_atim_window;
|
||||||
u32 ah_aifs;
|
|
||||||
u32 ah_cw_min;
|
|
||||||
u32 ah_cw_max;
|
|
||||||
u32 ah_limit_tx_retries;
|
u32 ah_limit_tx_retries;
|
||||||
u8 ah_coverage_class;
|
u8 ah_coverage_class;
|
||||||
|
|
||||||
|
@@ -119,8 +119,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||||||
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
||||||
ah->ah_imr = 0;
|
ah->ah_imr = 0;
|
||||||
ah->ah_atim_window = 0;
|
ah->ah_atim_window = 0;
|
||||||
ah->ah_aifs = AR5K_TUNE_AIFS;
|
|
||||||
ah->ah_cw_min = AR5K_TUNE_CWMIN;
|
|
||||||
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
|
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
|
||||||
ah->ah_software_retry = false;
|
ah->ah_software_retry = false;
|
||||||
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
|
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
|
||||||
|
@@ -849,9 +849,11 @@ ath5k_txq_setup(struct ath5k_softc *sc,
|
|||||||
struct ath5k_txq *txq;
|
struct ath5k_txq *txq;
|
||||||
struct ath5k_txq_info qi = {
|
struct ath5k_txq_info qi = {
|
||||||
.tqi_subtype = subtype,
|
.tqi_subtype = subtype,
|
||||||
.tqi_aifs = AR5K_TXQ_USEDEFAULT,
|
/* XXX: default values not correct for B and XR channels,
|
||||||
.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
|
* but who cares? */
|
||||||
.tqi_cw_max = AR5K_TXQ_USEDEFAULT
|
.tqi_aifs = AR5K_TUNE_AIFS,
|
||||||
|
.tqi_cw_min = AR5K_TUNE_CWMIN,
|
||||||
|
.tqi_cw_max = AR5K_TUNE_CWMAX
|
||||||
};
|
};
|
||||||
int qnum;
|
int qnum;
|
||||||
|
|
||||||
@@ -901,9 +903,11 @@ static int
|
|||||||
ath5k_beaconq_setup(struct ath5k_hw *ah)
|
ath5k_beaconq_setup(struct ath5k_hw *ah)
|
||||||
{
|
{
|
||||||
struct ath5k_txq_info qi = {
|
struct ath5k_txq_info qi = {
|
||||||
.tqi_aifs = AR5K_TXQ_USEDEFAULT,
|
/* XXX: default values not correct for B and XR channels,
|
||||||
.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
|
* but who cares? */
|
||||||
.tqi_cw_max = AR5K_TXQ_USEDEFAULT,
|
.tqi_aifs = AR5K_TUNE_AIFS,
|
||||||
|
.tqi_cw_min = AR5K_TUNE_CWMIN,
|
||||||
|
.tqi_cw_max = AR5K_TUNE_CWMAX,
|
||||||
/* NB: for dynamic turbo, don't enable any other interrupts */
|
/* NB: for dynamic turbo, don't enable any other interrupts */
|
||||||
.tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
|
.tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
|
||||||
};
|
};
|
||||||
@@ -937,7 +941,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
|
|||||||
*/
|
*/
|
||||||
qi.tqi_aifs = 0;
|
qi.tqi_aifs = 0;
|
||||||
qi.tqi_cw_min = 0;
|
qi.tqi_cw_min = 0;
|
||||||
qi.tqi_cw_max = 2 * ah->ah_cw_min;
|
qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
|
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
|
||||||
|
@@ -35,25 +35,59 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure cw is a power of 2 minus 1 and smaller than 1024
|
||||||
|
*/
|
||||||
|
static u16 ath5k_cw_validate(u16 cw_req)
|
||||||
|
{
|
||||||
|
u32 cw = 1;
|
||||||
|
cw_req = min(cw_req, (u16)1023);
|
||||||
|
|
||||||
|
while (cw < cw_req)
|
||||||
|
cw = (cw << 1) | 1;
|
||||||
|
|
||||||
|
return cw;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set properties for a transmit queue
|
* Set properties for a transmit queue
|
||||||
*/
|
*/
|
||||||
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
|
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
|
||||||
const struct ath5k_txq_info *queue_info)
|
const struct ath5k_txq_info *qinfo)
|
||||||
{
|
{
|
||||||
|
struct ath5k_txq_info *qi;
|
||||||
|
|
||||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||||
|
|
||||||
if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
qi = &ah->ah_txq[queue];
|
||||||
|
|
||||||
|
if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
|
/* copy and validate values */
|
||||||
|
qi->tqi_type = qinfo->tqi_type;
|
||||||
|
qi->tqi_subtype = qinfo->tqi_subtype;
|
||||||
|
qi->tqi_flags = qinfo->tqi_flags;
|
||||||
|
/*
|
||||||
|
* According to the docs: Although the AIFS field is 8 bit wide,
|
||||||
|
* the maximum supported value is 0xFC. Setting it higher than that
|
||||||
|
* will cause the DCU to hang.
|
||||||
|
*/
|
||||||
|
qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
|
||||||
|
qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
|
||||||
|
qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
|
||||||
|
qi->tqi_cbr_period = qinfo->tqi_cbr_period;
|
||||||
|
qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
|
||||||
|
qi->tqi_burst_time = qinfo->tqi_burst_time;
|
||||||
|
qi->tqi_ready_time = qinfo->tqi_ready_time;
|
||||||
|
|
||||||
/*XXX: Is this supported on 5210 ?*/
|
/*XXX: Is this supported on 5210 ?*/
|
||||||
if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
|
/*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
|
||||||
((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
|
if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
|
||||||
(queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
|
((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
|
||||||
queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
|
(qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
|
||||||
ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
|
qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
|
||||||
|
qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -186,7 +220,7 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||||||
*/
|
*/
|
||||||
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||||
{
|
{
|
||||||
u32 cw_min, cw_max, retry_lg, retry_sh;
|
u32 retry_lg, retry_sh;
|
||||||
struct ath5k_txq_info *tq = &ah->ah_txq[queue];
|
struct ath5k_txq_info *tq = &ah->ah_txq[queue];
|
||||||
|
|
||||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||||
@@ -217,14 +251,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||||||
/* Set IFS0 */
|
/* Set IFS0 */
|
||||||
if (ah->ah_turbo) {
|
if (ah->ah_turbo) {
|
||||||
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
|
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
|
||||||
(ah->ah_aifs + tq->tqi_aifs) *
|
tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) <<
|
||||||
AR5K_INIT_SLOT_TIME_TURBO) <<
|
|
||||||
AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
|
AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
|
||||||
AR5K_IFS0);
|
AR5K_IFS0);
|
||||||
} else {
|
} else {
|
||||||
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
|
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
|
||||||
(ah->ah_aifs + tq->tqi_aifs) *
|
tq->tqi_aifs * AR5K_INIT_SLOT_TIME) <<
|
||||||
AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
|
AR5K_IFS0_DIFS_S) |
|
||||||
AR5K_INIT_SIFS, AR5K_IFS0);
|
AR5K_INIT_SIFS, AR5K_IFS0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,35 +280,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||||||
AR5K_PHY_FRAME_CTL_5210);
|
AR5K_PHY_FRAME_CTL_5210);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate cwmin/max by channel mode
|
|
||||||
*/
|
|
||||||
cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
|
|
||||||
cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
|
|
||||||
ah->ah_aifs = AR5K_TUNE_AIFS;
|
|
||||||
/*XR is only supported on 5212*/
|
|
||||||
if (IS_CHAN_XR(ah->ah_current_channel) &&
|
|
||||||
ah->ah_version == AR5K_AR5212) {
|
|
||||||
cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
|
|
||||||
cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
|
|
||||||
ah->ah_aifs = AR5K_TUNE_AIFS_XR;
|
|
||||||
/*B mode is not supported on 5210*/
|
|
||||||
} else if (IS_CHAN_B(ah->ah_current_channel) &&
|
|
||||||
ah->ah_version != AR5K_AR5210) {
|
|
||||||
cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
|
|
||||||
cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
|
|
||||||
ah->ah_aifs = AR5K_TUNE_AIFS_11B;
|
|
||||||
}
|
|
||||||
|
|
||||||
cw_min = 1;
|
|
||||||
while (cw_min < ah->ah_cw_min)
|
|
||||||
cw_min = (cw_min << 1) | 1;
|
|
||||||
|
|
||||||
cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
|
|
||||||
((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
|
|
||||||
cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
|
|
||||||
((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate and set retry limits
|
* Calculate and set retry limits
|
||||||
*/
|
*/
|
||||||
@@ -292,7 +296,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||||||
/*No QCU/DCU [5210]*/
|
/*No QCU/DCU [5210]*/
|
||||||
if (ah->ah_version == AR5K_AR5210) {
|
if (ah->ah_version == AR5K_AR5210) {
|
||||||
ath5k_hw_reg_write(ah,
|
ath5k_hw_reg_write(ah,
|
||||||
(cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
|
(tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
|
||||||
| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
|
| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
|
||||||
AR5K_NODCU_RETRY_LMT_SLG_RETRY)
|
AR5K_NODCU_RETRY_LMT_SLG_RETRY)
|
||||||
| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
|
| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
|
||||||
@@ -314,14 +318,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||||||
/*===Rest is also for QCU/DCU only [5211+]===*/
|
/*===Rest is also for QCU/DCU only [5211+]===*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set initial content window (cw_min/cw_max)
|
* Set contention window (cw_min/cw_max)
|
||||||
* and arbitrated interframe space (aifs)...
|
* and arbitrated interframe space (aifs)...
|
||||||
*/
|
*/
|
||||||
ath5k_hw_reg_write(ah,
|
ath5k_hw_reg_write(ah,
|
||||||
AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
|
AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
|
||||||
AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
|
AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
|
||||||
AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
|
AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
|
||||||
AR5K_DCU_LCL_IFS_AIFS),
|
|
||||||
AR5K_QUEUE_DFS_LOCAL_IFS(queue));
|
AR5K_QUEUE_DFS_LOCAL_IFS(queue));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user