2010-11-23 19:20:30

by Nick Kossifidis

[permalink] [raw]
Subject: [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

* Replace set_slot_time with set_ifs_intervals that also sets
the various inter-frame space intervals based on current bwmode.

* Clean up AR5210 mess from reset_tx_queue, AR5210 only has one
data queue and we set IFS intervals for that queue on set_ifs_intervals
so there is nothing left to do for 5210 on reset_tx_queue.

Signed-off-by: Nick Kossifidis <[email protected]>
---
drivers/net/wireless/ath/ath5k/ath5k.h | 31 +--
drivers/net/wireless/ath/ath5k/pcu.c | 4 +-
drivers/net/wireless/ath/ath5k/qcu.c | 513 ++++++++++++++++++--------------
drivers/net/wireless/ath/ath5k/reg.h | 3 +-
4 files changed, 308 insertions(+), 243 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 7df5b46..ddbbf4c 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -222,34 +222,15 @@

/* Initial values */
#define AR5K_INIT_CYCRSSI_THR1 2
-#define AR5K_INIT_TX_LATENCY 502
-#define AR5K_INIT_USEC 39
-#define AR5K_INIT_USEC_TURBO 79
-#define AR5K_INIT_USEC_32 31
-#define AR5K_INIT_SLOT_TIME_CLOCK 396
-#define AR5K_INIT_SLOT_TIME_TURBO_CLOCK 480
-#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
-#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
-#define AR5K_INIT_PROG_IFS 920
-#define AR5K_INIT_PROG_IFS_TURBO 960
-#define AR5K_INIT_EIFS 3440
-#define AR5K_INIT_EIFS_TURBO 6880
-#define AR5K_INIT_SIFS_CLOCK 560
-#define AR5K_INIT_SIFS_TURBO_CLOCK 480
+
+/* Tx retry limits */
#define AR5K_INIT_SH_RETRY 10
#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
+/* For station mode */
#define AR5K_INIT_SSH_RETRY 32
#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
#define AR5K_INIT_TX_RETRY 10

-#define AR5K_INIT_PROTO_TIME_CNTRL ( \
- (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
- (AR5K_INIT_PROG_IFS) \
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
- (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
- (AR5K_INIT_PROG_IFS_TURBO) \
-)

/* Slot time */
#define AR5K_INIT_SLOT_TIME_TURBO 6
@@ -1240,6 +1221,10 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);


/* Protocol Control Unit Functions */
+/* Helpers */
+int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+ int len, struct ieee80211_rate *rate);
+unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* RX filter control*/
@@ -1273,7 +1258,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
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_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time);
/* Init function */
int ath5k_hw_init_queues(struct ath5k_hw *ah);

diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index e691378..4556f29 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -763,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
* @ah: The &struct ath5k_hw
* @coverage_class: IEEE 802.11 coverage class number
*
- * Sets slot time, ACK timeout and CTS timeout for given coverage class.
+ * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
*/
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
{
@@ -772,7 +772,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
int cts_timeout = ack_timeout;

- ath5k_hw_set_slot_time(ah, slot_time);
+ ath5k_hw_set_ifs_intervals(ah, slot_time);
ath5k_hw_set_ack_timeout(ah, ack_timeout);
ath5k_hw_set_cts_timeout(ah, cts_timeout);

diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 6eb6838..e13142a 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -276,8 +276,14 @@ static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
return;
}

-/*
- * Set DFS properties for a transmit queue on DCU
+/**
+ * ath5k_hw_reset_tx_queue - Initialize a single hw queue
+ *
+ * @ah The &struct ath5k_hw
+ * @queue The hw queue number
+ *
+ * Set DFS properties for the given transmit queue on DCU
+ * and configures all queue-specific parameters.
*/
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
{
@@ -287,240 +293,217 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)

tq = &ah->ah_txq[queue];

- if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ /* Skip if queue inactive or if we are on AR5210
+ * that doesn't have QCU/DCU */
+ if ((ah->ah_version == AR5K_AR5210) ||
+ (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
return 0;

- if (ah->ah_version == AR5K_AR5210) {
- /* Only handle data queues, others will be ignored */
- if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
- return 0;
-
- /* Set Slot time */
- ath5k_hw_reg_write(ah, (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ?
- AR5K_INIT_SLOT_TIME_TURBO_CLOCK :
- AR5K_INIT_SLOT_TIME_CLOCK,
- AR5K_SLOT_TIME);
- /* Set ACK_CTS timeout */
- ath5k_hw_reg_write(ah, (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ?
- AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
- AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
-
- /* Set IFS0 */
- if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO_CLOCK +
- tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO_CLOCK)
- << AR5K_IFS0_DIFS_S) |
- AR5K_INIT_SIFS_TURBO_CLOCK,
- AR5K_IFS0);
- } else {
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_CLOCK +
- tq->tqi_aifs * AR5K_INIT_SLOT_TIME_CLOCK) <<
- AR5K_IFS0_DIFS_S) |
- AR5K_INIT_SIFS_CLOCK, AR5K_IFS0);
- }
-
- /* Set IFS1 */
- ath5k_hw_reg_write(ah, (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ?
- AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
- AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
- } else {
-
- /*===Rest is also for QCU/DCU only [5211+]===*/
-
- /*
- * Set contention window (cw_min/cw_max)
- * and arbitrated interframe space (aifs)...
- */
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
- AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
- AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
- AR5K_QUEUE_DFS_LOCAL_IFS(queue));
-
- /*
- * Set tx retry limits for this queue
- */
- ath5k_hw_set_tx_retry_limits(ah, queue);
-
- /*
- * Set misc registers
- */
-
- /* Enable DCU to wait for next fragment from QCU */
+ /*
+ * Set contention window (cw_min/cw_max)
+ * and arbitrated interframe space (aifs)...
+ */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+ /*
+ * Set tx retry limits for this queue
+ */
+ ath5k_hw_set_tx_retry_limits(ah, queue);
+
+
+ /*
+ * Set misc registers
+ */
+
+ /* Enable DCU to wait for next fragment from QCU */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_DCU_MISC_FRAG_WAIT);
+
+ /* On Maui and Spirit use the global seqnum on DCU */
+ if (ah->ah_mac_version < AR5K_SREV_AR5211)
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- AR5K_DCU_MISC_FRAG_WAIT);
+ AR5K_DCU_MISC_SEQNUM_CTL);

- /* On Maui and Spirit use the global seqnum on DCU */
- if (ah->ah_mac_version < AR5K_SREV_AR5211)
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- AR5K_DCU_MISC_SEQNUM_CTL);
+ /* Constant bit rate period */
+ if (tq->tqi_cbr_period) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+ AR5K_QCU_CBRCFG_INTVAL) |
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+ AR5K_QCU_CBRCFG_ORN_THRES),
+ AR5K_QUEUE_CBRCFG(queue));

- if (tq->tqi_cbr_period) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
- AR5K_QCU_CBRCFG_INTVAL) |
- AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
- AR5K_QCU_CBRCFG_ORN_THRES),
- AR5K_QUEUE_CBRCFG(queue));
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_CBR);
+
+ if (tq->tqi_cbr_overflow_limit)
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_CBR);
- if (tq->tqi_cbr_overflow_limit)
- AR5K_REG_ENABLE_BITS(ah,
- AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_CBR_THRES_ENABLE);
- }
+ }

- if (tq->tqi_ready_time &&
- (tq->tqi_type != AR5K_TX_QUEUE_CAB))
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
- AR5K_QCU_RDYTIMECFG_INTVAL) |
- AR5K_QCU_RDYTIMECFG_ENABLE,
- AR5K_QUEUE_RDYTIMECFG(queue));
+ /* Ready time interval */
+ if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));

- if (tq->tqi_burst_time) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
- AR5K_DCU_CHAN_TIME_DUR) |
- AR5K_DCU_CHAN_TIME_ENABLE,
- AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+ if (tq->tqi_burst_time) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+ AR5K_DCU_CHAN_TIME_DUR) |
+ AR5K_DCU_CHAN_TIME_ENABLE,
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));

- if (tq->tqi_flags
- & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
- AR5K_REG_ENABLE_BITS(ah,
- AR5K_QUEUE_MISC(queue),
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_RDY_VEOL_POLICY);
- }
+ }

- if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
- ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
- AR5K_QUEUE_DFS_MISC(queue));
+ /* Enable/disable Post frame backoff */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+ AR5K_QUEUE_DFS_MISC(queue));

- if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
- ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
- AR5K_QUEUE_DFS_MISC(queue));
+ /* Enable/disable fragmentation burst backoff */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+ AR5K_QUEUE_DFS_MISC(queue));

- /*
- * Set registers by queue type
- */
- switch (tq->tqi_type) {
- case AR5K_TX_QUEUE_BEACON:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ /*
+ * Set registers by queue type
+ */
+ switch (tq->tqi_type) {
+ case AR5K_TX_QUEUE_BEACON:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_FRSHED_DBA_GT |
AR5K_QCU_MISC_CBREXP_BCN_DIS |
AR5K_QCU_MISC_BCN_ENABLE);

- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
AR5K_DCU_MISC_ARBLOCK_CTL_S) |
AR5K_DCU_MISC_ARBLOCK_IGNORE |
AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
AR5K_DCU_MISC_BCN_ENABLE);
- break;
+ break;

- case AR5K_TX_QUEUE_CAB:
- /* XXX: use BCN_SENT_GT, if we can figure out how */
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_DBA_GT |
- AR5K_QCU_MISC_CBREXP_DIS |
- AR5K_QCU_MISC_CBREXP_BCN_DIS);
+ case AR5K_TX_QUEUE_CAB:
+ /* XXX: use BCN_SENT_GT, if we can figure out how */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_CBREXP_DIS |
+ AR5K_QCU_MISC_CBREXP_BCN_DIS);

- ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
- (AR5K_TUNE_SW_BEACON_RESP -
- AR5K_TUNE_DMA_BEACON_RESP) -
+ ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
+ (AR5K_TUNE_SW_BEACON_RESP -
+ AR5K_TUNE_DMA_BEACON_RESP) -
AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
- AR5K_QCU_RDYTIMECFG_ENABLE,
- AR5K_QUEUE_RDYTIMECFG(queue));
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));

- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
- AR5K_DCU_MISC_ARBLOCK_CTL_S));
- break;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+ AR5K_DCU_MISC_ARBLOCK_CTL_S));
+ break;

- case AR5K_TX_QUEUE_UAPSD:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_CBREXP_DIS);
- break;
+ case AR5K_TX_QUEUE_UAPSD:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBREXP_DIS);
+ break;

- case AR5K_TX_QUEUE_DATA:
- default:
+ case AR5K_TX_QUEUE_DATA:
+ default:
break;
- }
-
- /* TODO: Handle frame compression */
-
- /*
- * Enable interrupts for this tx queue
- * in the secondary interrupt mask registers
- */
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
-
- /* Update secondary interrupt mask registers */
-
- /* Filter out inactive queues */
- ah->ah_txq_imr_txok &= ah->ah_txq_status;
- ah->ah_txq_imr_txerr &= ah->ah_txq_status;
- ah->ah_txq_imr_txurn &= ah->ah_txq_status;
- ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
- ah->ah_txq_imr_txeol &= ah->ah_txq_status;
- ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
- ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
- ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
- ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
-
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
- AR5K_SIMR0_QCU_TXOK) |
- AR5K_REG_SM(ah->ah_txq_imr_txdesc,
- AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
- AR5K_SIMR1_QCU_TXERR) |
- AR5K_REG_SM(ah->ah_txq_imr_txeol,
- AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
- /* Update simr2 but don't overwrite rest simr2 settings */
- AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
- AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
- AR5K_REG_SM(ah->ah_txq_imr_txurn,
- AR5K_SIMR2_QCU_TXURN));
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
- AR5K_SIMR3_QCBRORN) |
- AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
- AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
- AR5K_SIMR4_QTRIG), AR5K_SIMR4);
- /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
- AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
- /* No queue has TXNOFRM enabled, disable the interrupt
- * by setting AR5K_TXNOFRM to zero */
- if (ah->ah_txq_imr_nofrm == 0)
- ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
-
- /* Set QCU mask for this DCU to save power */
- AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
}

+ /* TODO: Handle frame compression */
+
+ /*
+ * Enable interrupts for this tx queue
+ * in the secondary interrupt mask registers
+ */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
+
+ /* Update secondary interrupt mask registers */
+
+ /* Filter out inactive queues */
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+ ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+ AR5K_SIMR0_QCU_TXOK) |
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+ AR5K_SIMR0_QCU_TXDESC),
+ AR5K_SIMR0);
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+ AR5K_SIMR1_QCU_TXERR) |
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
+ AR5K_SIMR1_QCU_TXEOL),
+ AR5K_SIMR1);
+
+ /* Update SIMR2 but don't overwrite rest simr2 settings */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+ AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN));
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+ AR5K_SIMR3_QCBRORN) |
+ AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+ AR5K_SIMR3_QCBRURN),
+ AR5K_SIMR3);
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+ AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+
+ /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+ AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+
+ /* No queue has TXNOFRM enabled, disable the interrupt
+ * by setting AR5K_TXNOFRM to zero */
+ if (ah->ah_txq_imr_nofrm == 0)
+ ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+ /* Set QCU mask for this DCU to save power */
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
+
return 0;
}

@@ -529,24 +512,114 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
* Global QCU/DCU functions *
\**************************/

-/*
- * Set slot time on DCU
+/**
+ * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU
+ *
+ * @ah The &struct ath5k_hw
+ * @slot_time Slot time in us
+ *
+ * Sets the global IFS intervals on DCU (also works on AR5210) for
+ * the given slot time and the current bwmode.
*/
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
{
+ struct ieee80211_channel *channel = ah->ah_current_channel;
+ struct ath5k_softc *sc = ah->ah_sc;
+ struct ieee80211_rate *rate;
+ u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);

if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
return -EINVAL;

- if (ah->ah_version == AR5K_AR5210)
+ sifs = ath5k_hw_get_default_sifs(ah);
+ sifs_clock = ath5k_hw_htoclock(ah, sifs);
+
+ /* EIFS
+ * Txtime of ack at lowest rate + SIFS + DIFS
+ * (DIFS = SIFS + 2 * Slot time)
+ *
+ * Note: HAL has some predefined values for EIFS
+ * Turbo: (37 + 2 * 6)
+ * Default: (74 + 2 * 9)
+ * Half: (149 + 2 * 13)
+ * Quarter: (298 + 2 * 21)
+ *
+ * (74 + 2 * 6) for AR5210 default and turbo !
+ *
+ * According to the formula we have
+ * ack_tx_time = 25 for turbo and
+ * ack_tx_time = 42.5 * clock multiplier
+ * for default/half/quarter.
+ *
+ * This can't be right, 42 is what we would get
+ * from ath5k_hw_get_frame_dur_for_bwmode or
+ * ieee80211_generic_frame_duration for zero frame
+ * length and without SIFS !
+ *
+ * Also we have different lowest rate for 802.11a
+ */
+ if (channel->hw_value & CHANNEL_5GHZ)
+ rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
+ else
+ rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+
+ ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+
+ /* ack_tx_time includes an SIFS already */
+ eifs = ack_tx_time + sifs + 2 * slot_time;
+ eifs_clock = ath5k_hw_htoclock(ah, eifs);
+
+ /* Set IFS settings on AR5210 */
+ if (ah->ah_version == AR5K_AR5210) {
+ u32 pifs, pifs_clock, difs, difs_clock;
+
+ /* Set slot time */
ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
- else
- ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+
+ /* Set EIFS */
+ eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
+
+ /* PIFS = Slot time + SIFS */
+ pifs = slot_time + sifs;
+ pifs_clock = ath5k_hw_htoclock(ah, pifs);
+ pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
+
+ /* DIFS = SIFS + 2 * Slot time */
+ difs = sifs + 2 * slot_time;
+ difs_clock = ath5k_hw_htoclock(ah, difs);
+
+ /* Set SIFS/DIFS */
+ ath5k_hw_reg_write(ah, (difs_clock <<
+ AR5K_IFS0_DIFS_S) | sifs_clock,
+ AR5K_IFS0);
+
+ /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
+ ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
+ (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
+ AR5K_IFS1);
+
+ return 0;
+ }
+
+ /* Set IFS slot time */
+ ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+
+ /* Set EIFS interval */
+ ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
+
+ /* Set SIFS interval in usecs */
+ AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+ AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
+ sifs);
+
+ /* Set SIFS interval in clock cycles */
+ ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);

return 0;
}

+
int ath5k_hw_init_queues(struct ath5k_hw *ah)
{
int i, ret;
@@ -559,14 +632,20 @@ int ath5k_hw_init_queues(struct ath5k_hw *ah)
* This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
* Note: If we want we can assign multiple qcus on one dcu.
*/
- for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
- ret = ath5k_hw_reset_tx_queue(ah, i);
- if (ret) {
- ATH5K_ERR(ah->ah_sc,
- "failed to reset TX queue #%d\n", i);
- return ret;
+ if (ah->ah_version != AR5K_AR5210)
+ for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
+ ret = ath5k_hw_reset_tx_queue(ah, i);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc,
+ "failed to reset TX queue #%d\n", i);
+ return ret;
+ }
}
- }
+ else
+ /* No QCU/DCU on AR5210, just set tx
+ * retry limits. We set IFS parameters
+ * on ath5k_hw_set_ifs_intervals */
+ ath5k_hw_set_tx_retry_limits(ah, 0);

return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index dc213bb..8516728 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -787,6 +787,7 @@
#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */
#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */
#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S 4
#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */
#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10
#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */
@@ -1311,7 +1312,7 @@
#define AR5K_IFS1_EIFS 0x03fff000
#define AR5K_IFS1_EIFS_S 12
#define AR5K_IFS1_CS_EN 0x04000000
-
+#define AR5K_IFS1_CS_EN_S 26

/*
* CFP duration register


2010-11-26 00:54:45

by Jonathan Guerin

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

On Thu, Nov 25, 2010 at 8:41 AM, Jonathan Guerin <[email protected]> wrote:
> On Wed, Nov 24, 2010 at 10:55 PM, Nick Kossifidis <[email protected]> wrote:
>> 2010/11/24 Jonathan Guerin <[email protected]>:
>>>
>>>> diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
>>>> index e691378..4556f29 100644
>>>> --- a/drivers/net/wireless/ath/ath5k/pcu.c
>>>> +++ b/drivers/net/wireless/ath/ath5k/pcu.c
>>>> @@ -763,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
>>>> * @ah: The &struct ath5k_hw
>>>> * @coverage_class: IEEE 802.11 coverage class number
>>>> *
>>>> - * Sets slot time, ACK timeout and CTS timeout for given coverage class.
>>>> + * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
>>>> */
>>>> void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>>> {
>>>> @@ -772,7 +772,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>>> int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
>>>
>>> This is not quite right:
>>>
>>> According to the 802.11-2007 spec document, the ACKTimeout value is
>>> (Section 9.2.8 ACK procedure):
>>> ACKTimeout = aSIFSTime + aSlotTime + aPHY-RX-START-Delay
>>>
>>> From Table 17-15--OFDM PHY characteristics, the values are:
>>> aSIFSTime = 16
>>> aSlotTime = 9
>>> aPHY-RX-START-Delay = 25
>>>
>>> Therefore, ACKTimeout = 50
>>>
>>> Ignoring my uniformed comments from before, this is the only thing I
>>> can see that's wrong.
>>>
>>> Cheers,
>>>
>>> Jonathan
>>
>> Hmm I didn't mess with set_coverage_class so i didn't look up for ack
>> timeout. That phy-rx-start-delay is standard value or hw specific ?
>> Also does it change with clockrate (bwmodes) ? We already have a phy
>> activation -> rx start delay (check patch 25). It's 10.000 on RF5111
>> and 2.000 on RF5112 and later, if we divide by A clock it's 250 on
>> RF5111 and 50 on RF5112 and later. Do you think it's related ?
>
> The phy-rx-start-delay is set in the standard. I'll find you the
> relevant pages soon.

The aPHY-RX-START-Delay value is specific per PHY. In the case of
OFDM, you can find the relevant timings at:

Table 17-15--OFDM PHY characteristics
aPHY-RX-START-Delay 25 ?s (20MHz) 49 ?s (10MHz) 97 ?s (5MHz)

>
> I'll look up the others tomorrow. I'm feeling pretty sick today, so
> not sure if I'll get a chance.

I just a quick look at the code. The first thing that pops to mind and
that is apparent in the Table mentioned above, you can't just multiply
by 2 every time you halve the channel - the value is actually slightly
shorter than this.

Secondly, I'm assuming that the AR5K_PHY_RX_DELAY register refers to
the aPHY-RX-START-Delay value from the standard. It would make sense
that the card require this value, as it is necessary in resetting the
NAV (9.2.5.4 Setting and resetting the NAV), for CTS timeouts (9.2.5.7
CTS procedure), & ACK Timeouts (9.2.8 ACK procedure). The first 2
cases both refer to station behaviour after an RTS frame, but are
slightly different in that one is from an overhearing station, whereas
the the second is from the sending station. In the driver, which case
is the CTSTimeout value used for?

Cheers,

Jonathan

>
> Cheers,
>
> Jonathan
>
>>
>> --
>> GPG ID: 0xD21DB2DB
>> As you read this post global entropy rises. Have Fun ;-)
>> Nick
>>
>

2010-11-27 02:05:29

by Lukáš Turek

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

On Saturday 27 November 2010 02:31:53 Nick Kossifidis wrote:
> When we convert to core clock units it's what we should do, all
> timings should change the same way. I don't know what this
> aPHY-RX-START-Delay is but if it changes that way we can use absolute
> values as we do for slot time and sifs.

Although aPHY-RX-START-Delay is specified in the standard, it's not needed on
Atheros hardware, probably the hardware starts the timeout countdown after it
switches to RX mode (so aPHY-RX-START-Delay is added implicitly). See my
discussion with Felix Fietkau a year ago, starting here:
http://www.mail-archive.com/[email protected]/msg02810.html

The calculation used in set_coverage_class is also the same as the one in
Madwifi driver. When I wrote that code, I intentionally kept the old initvals
when no coverage class was set to prevent regressions (the ACK timeout in
initivals is larger than the one for coverage class 0, so a long distance link
that worked before would break). Maybe I was too careful.

Lukas Turek


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part.

2010-11-24 01:54:43

by Jonathan Guerin

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

My apologies for not reading the patches properly. I like these a LOT
- they make things so much neater and understandable.

On Wed, Nov 24, 2010 at 5:19 AM, Nick Kossifidis <[email protected]> wrote:
> ?* Replace set_slot_time with set_ifs_intervals that also sets
> ?the various inter-frame space intervals based on current bwmode.
>
> ?* Clean up AR5210 mess from reset_tx_queue, AR5210 only has one
> ?data queue and we set IFS intervals for that queue on set_ifs_intervals
> ?so there is nothing left to do for 5210 on reset_tx_queue.
>
> ?Signed-off-by: Nick Kossifidis <[email protected]>
> ---
> ?drivers/net/wireless/ath/ath5k/ath5k.h | ? 31 +--
> ?drivers/net/wireless/ath/ath5k/pcu.c ? | ? ?4 +-
> ?drivers/net/wireless/ath/ath5k/qcu.c ? | ?513 ++++++++++++++++++--------------
> ?drivers/net/wireless/ath/ath5k/reg.h ? | ? ?3 +-
> ?4 files changed, 308 insertions(+), 243 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
> index 7df5b46..ddbbf4c 100644
> --- a/drivers/net/wireless/ath/ath5k/ath5k.h
> +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
> @@ -222,34 +222,15 @@
>
> ?/* Initial values */
> ?#define ? ? ? ?AR5K_INIT_CYCRSSI_THR1 ? ? ? ? ? ? ? ? ?2
> -#define AR5K_INIT_TX_LATENCY ? ? ? ? ? ? ? ? ? 502
> -#define AR5K_INIT_USEC ? ? ? ? ? ? ? ? ? ? ? ? 39
> -#define AR5K_INIT_USEC_TURBO ? ? ? ? ? ? ? ? ? 79
> -#define AR5K_INIT_USEC_32 ? ? ? ? ? ? ? ? ? ? ?31
> -#define AR5K_INIT_SLOT_TIME_CLOCK ? ? ? ? ? ? ?396
> -#define AR5K_INIT_SLOT_TIME_TURBO_CLOCK ? ? ? ? ? ? ? ?480
> -#define AR5K_INIT_ACK_CTS_TIMEOUT ? ? ? ? ? ? ?1024
> -#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO ? ? ? ? ? ? ? ?0x08000800
> -#define AR5K_INIT_PROG_IFS ? ? ? ? ? ? ? ? ? ? 920
> -#define AR5K_INIT_PROG_IFS_TURBO ? ? ? ? ? ? ? 960
> -#define AR5K_INIT_EIFS ? ? ? ? ? ? ? ? ? ? ? ? 3440
> -#define AR5K_INIT_EIFS_TURBO ? ? ? ? ? ? ? ? ? 6880
> -#define AR5K_INIT_SIFS_CLOCK ? ? ? ? ? ? ? ? ? 560
> -#define AR5K_INIT_SIFS_TURBO_CLOCK ? ? ? ? ? ? 480
> +
> +/* Tx retry limits */
> ?#define AR5K_INIT_SH_RETRY ? ? ? ? ? ? ? ? ? ? 10
> ?#define AR5K_INIT_LG_RETRY ? ? ? ? ? ? ? ? ? ? AR5K_INIT_SH_RETRY
> +/* For station mode */
> ?#define AR5K_INIT_SSH_RETRY ? ? ? ? ? ? ? ? ? ?32
> ?#define AR5K_INIT_SLG_RETRY ? ? ? ? ? ? ? ? ? ?AR5K_INIT_SSH_RETRY
> ?#define AR5K_INIT_TX_RETRY ? ? ? ? ? ? ? ? ? ? 10
>
> -#define AR5K_INIT_PROTO_TIME_CNTRL ? ? ? ? ? ? ( ? ? ? ? ? ? ? ? ? ? ? \
> - ? ? ? (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | ? ? ?\
> - ? ? ? (AR5K_INIT_PROG_IFS) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
> -)
> -#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ? ? ? ( ? ? ? ? ? ? ? ? ? ? ? \
> - ? ? ? (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
> - ? ? ? (AR5K_INIT_PROG_IFS_TURBO) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
> -)
>
> ?/* Slot time */
> ?#define AR5K_INIT_SLOT_TIME_TURBO ? ? ? ? ? ? ?6
> @@ -1240,6 +1221,10 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
>
>
> ?/* Protocol Control Unit Functions */
> +/* Helpers */
> +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
> + ? ? ? ? ? ? ? int len, struct ieee80211_rate *rate);
> +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
> ?extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
> ?void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
> ?/* RX filter control*/
> @@ -1273,7 +1258,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
> ?u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
> ?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_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
> +int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time);
> ?/* Init function */
> ?int ath5k_hw_init_queues(struct ath5k_hw *ah);
>
> diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
> index e691378..4556f29 100644
> --- a/drivers/net/wireless/ath/ath5k/pcu.c
> +++ b/drivers/net/wireless/ath/ath5k/pcu.c
> @@ -763,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
> ?* @ah: The &struct ath5k_hw
> ?* @coverage_class: IEEE 802.11 coverage class number
> ?*
> - * Sets slot time, ACK timeout and CTS timeout for given coverage class.
> + * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
> ?*/
> ?void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
> ?{
> @@ -772,7 +772,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
> ? ? ? ?int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;

This is not quite right:

According to the 802.11-2007 spec document, the ACKTimeout value is
(Section 9.2.8 ACK procedure):
ACKTimeout = aSIFSTime + aSlotTime + aPHY-RX-START-Delay

>From Table 17-15?OFDM PHY characteristics, the values are:
aSIFSTime = 16
aSlotTime = 9
aPHY-RX-START-Delay = 25

Therefore, ACKTimeout = 50

Ignoring my uniformed comments from before, this is the only thing I
can see that's wrong.

Cheers,

Jonathan

> ? ? ? ?int cts_timeout = ack_timeout;
>
> - ? ? ? ath5k_hw_set_slot_time(ah, slot_time);
> + ? ? ? ath5k_hw_set_ifs_intervals(ah, slot_time);
> ? ? ? ?ath5k_hw_set_ack_timeout(ah, ack_timeout);
> ? ? ? ?ath5k_hw_set_cts_timeout(ah, cts_timeout);
>
> diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
> index 6eb6838..e13142a 100644
> --- a/drivers/net/wireless/ath/ath5k/qcu.c
> +++ b/drivers/net/wireless/ath/ath5k/qcu.c
> @@ -276,8 +276,14 @@ static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
> ? ? ? ?return;
> ?}
>
> -/*
> - * Set DFS properties for a transmit queue on DCU
> +/**
> + * ath5k_hw_reset_tx_queue - Initialize a single hw queue
> + *
> + * @ah The &struct ath5k_hw
> + * @queue The hw queue number
> + *
> + * Set DFS properties for the given transmit queue on DCU
> + * and configures all queue-specific parameters.
> ?*/
> ?int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
> ?{
> @@ -287,240 +293,217 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
>
> ? ? ? ?tq = &ah->ah_txq[queue];
>
> - ? ? ? if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
> + ? ? ? /* Skip if queue inactive or if we are on AR5210
> + ? ? ? ?* that doesn't have QCU/DCU */
> + ? ? ? if ((ah->ah_version == AR5K_AR5210) ||
> + ? ? ? (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
> ? ? ? ? ? ? ? ?return 0;
>
> - ? ? ? if (ah->ah_version == AR5K_AR5210) {
> - ? ? ? ? ? ? ? /* Only handle data queues, others will be ignored */
> - ? ? ? ? ? ? ? if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
> - ? ? ? ? ? ? ? ? ? ? ? return 0;
> -
> - ? ? ? ? ? ? ? /* Set Slot time */
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ?
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_SLOT_TIME_TURBO_CLOCK :
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_SLOT_TIME_CLOCK,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SLOT_TIME);
> - ? ? ? ? ? ? ? /* Set ACK_CTS timeout */
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ?
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
> -
> - ? ? ? ? ? ? ? /* Set IFS0 */
> - ? ? ? ? ? ? ? if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO_CLOCK +
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO_CLOCK)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? << AR5K_IFS0_DIFS_S) |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_SIFS_TURBO_CLOCK,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_IFS0);
> - ? ? ? ? ? ? ? } else {
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_CLOCK +
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tq->tqi_aifs * AR5K_INIT_SLOT_TIME_CLOCK) <<
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_IFS0_DIFS_S) |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_SIFS_CLOCK, AR5K_IFS0);
> - ? ? ? ? ? ? ? }
> -
> - ? ? ? ? ? ? ? /* Set IFS1 */
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ?
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
> - ? ? ? } else {
> -
> - ? ? ? /*===Rest is also for QCU/DCU only [5211+]===*/
> -
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Set contention window (cw_min/cw_max)
> - ? ? ? ? ? ? ? ?* and arbitrated interframe space (aifs)...
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_LOCAL_IFS(queue));
> -
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Set tx retry limits for this queue
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? ath5k_hw_set_tx_retry_limits(ah, queue);
> -
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Set misc registers
> - ? ? ? ? ? ? ? ?*/
> -
> - ? ? ? ? ? ? ? /* Enable DCU to wait for next fragment from QCU */
> + ? ? ? /*
> + ? ? ? ?* Set contention window (cw_min/cw_max)
> + ? ? ? ?* and arbitrated interframe space (aifs)...
> + ? ? ? ?*/
> + ? ? ? ath5k_hw_reg_write(ah,
> + ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
> + ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
> + ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
> + ? ? ? ? ? ? ? AR5K_QUEUE_DFS_LOCAL_IFS(queue));
> +
> + ? ? ? /*
> + ? ? ? ?* Set tx retry limits for this queue
> + ? ? ? ?*/
> + ? ? ? ath5k_hw_set_tx_retry_limits(ah, queue);
> +
> +
> + ? ? ? /*
> + ? ? ? ?* Set misc registers
> + ? ? ? ?*/
> +
> + ? ? ? /* Enable DCU to wait for next fragment from QCU */
> + ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_MISC_FRAG_WAIT);
> +
> + ? ? ? /* On Maui and Spirit use the global seqnum on DCU */
> + ? ? ? if (ah->ah_mac_version < AR5K_SREV_AR5211)
> ? ? ? ? ? ? ? ?AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_MISC_FRAG_WAIT);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_MISC_SEQNUM_CTL);
>
> - ? ? ? ? ? ? ? /* On Maui and Spirit use the global seqnum on DCU */
> - ? ? ? ? ? ? ? if (ah->ah_mac_version < AR5K_SREV_AR5211)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_MISC_SEQNUM_CTL);
> + ? ? ? /* Constant bit rate period */
> + ? ? ? if (tq->tqi_cbr_period) {
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_CBRCFG_INTVAL) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_CBRCFG_ORN_THRES),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_CBRCFG(queue));
>
> - ? ? ? ? ? ? ? if (tq->tqi_cbr_period) {
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_CBRCFG_INTVAL) |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_CBRCFG_ORN_THRES),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_CBRCFG(queue));
> + ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_FRSHED_CBR);
> +
> + ? ? ? ? ? ? ? if (tq->tqi_cbr_overflow_limit)
> ? ? ? ? ? ? ? ? ? ? ? ?AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_FRSHED_CBR);
> - ? ? ? ? ? ? ? ? ? ? ? if (tq->tqi_cbr_overflow_limit)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_MISC(queue),
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_QCU_MISC_CBR_THRES_ENABLE);
> - ? ? ? ? ? ? ? }
> + ? ? ? }
>
> - ? ? ? ? ? ? ? if (tq->tqi_ready_time &&
> - ? ? ? ? ? ? ? (tq->tqi_type != AR5K_TX_QUEUE_CAB))
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_RDYTIMECFG_INTVAL) |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_RDYTIMECFG_ENABLE,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_RDYTIMECFG(queue));
> + ? ? ? /* Ready time interval */
> + ? ? ? if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_RDYTIMECFG_INTVAL) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_RDYTIMECFG_ENABLE,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_RDYTIMECFG(queue));
>
> - ? ? ? ? ? ? ? if (tq->tqi_burst_time) {
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_CHAN_TIME_DUR) |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_CHAN_TIME_ENABLE,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
> + ? ? ? if (tq->tqi_burst_time) {
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_CHAN_TIME_DUR) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_CHAN_TIME_ENABLE,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
>
> - ? ? ? ? ? ? ? ? ? ? ? if (tq->tqi_flags
> - ? ? ? ? ? ? ? ? ? ? ? & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_MISC(queue),
> + ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
> + ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_QCU_MISC_RDY_VEOL_POLICY);
> - ? ? ? ? ? ? ? }
> + ? ? ? }
>
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_MISC(queue));
> + ? ? ? /* Enable/disable Post frame backoff */
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_MISC(queue));
>
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_MISC(queue));
> + ? ? ? /* Enable/disable fragmentation burst backoff */
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_DFS_MISC(queue));
>
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Set registers by queue type
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? switch (tq->tqi_type) {
> - ? ? ? ? ? ? ? case AR5K_TX_QUEUE_BEACON:
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> + ? ? ? /*
> + ? ? ? ?* Set registers by queue type
> + ? ? ? ?*/
> + ? ? ? switch (tq->tqi_type) {
> + ? ? ? case AR5K_TX_QUEUE_BEACON:
> + ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_QCU_MISC_FRSHED_DBA_GT |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_QCU_MISC_CBREXP_BCN_DIS |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_QCU_MISC_BCN_ENABLE);
>
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> + ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_DCU_MISC_ARBLOCK_CTL_S) |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_DCU_MISC_ARBLOCK_IGNORE |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_DCU_MISC_BCN_ENABLE);
> - ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? break;
>
> - ? ? ? ? ? ? ? case AR5K_TX_QUEUE_CAB:
> - ? ? ? ? ? ? ? ? ? ? ? /* XXX: use BCN_SENT_GT, if we can figure out how */
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_FRSHED_DBA_GT |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_CBREXP_DIS |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_CBREXP_BCN_DIS);
> + ? ? ? case AR5K_TX_QUEUE_CAB:
> + ? ? ? ? ? ? ? /* XXX: use BCN_SENT_GT, if we can figure out how */
> + ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_FRSHED_DBA_GT |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_CBREXP_DIS |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_CBREXP_BCN_DIS);
>
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (AR5K_TUNE_SW_BEACON_RESP -
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_TUNE_DMA_BEACON_RESP) -
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (AR5K_TUNE_SW_BEACON_RESP -
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_TUNE_DMA_BEACON_RESP) -
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_RDYTIMECFG_ENABLE,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_RDYTIMECFG(queue));
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_RDYTIMECFG_ENABLE,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QUEUE_RDYTIMECFG(queue));
>
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_MISC_ARBLOCK_CTL_S));
> - ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_MISC_ARBLOCK_CTL_S));
> + ? ? ? ? ? ? ? break;
>
> - ? ? ? ? ? ? ? case AR5K_TX_QUEUE_UAPSD:
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_CBREXP_DIS);
> - ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? case AR5K_TX_QUEUE_UAPSD:
> + ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_QCU_MISC_CBREXP_DIS);
> + ? ? ? ? ? ? ? break;
>
> - ? ? ? ? ? ? ? case AR5K_TX_QUEUE_DATA:
> - ? ? ? ? ? ? ? default:
> + ? ? ? case AR5K_TX_QUEUE_DATA:
> + ? ? ? default:
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> - ? ? ? ? ? ? ? }
> -
> - ? ? ? ? ? ? ? /* TODO: Handle frame compression */
> -
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Enable interrupts for this tx queue
> - ? ? ? ? ? ? ? ?* in the secondary interrupt mask registers
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
> -
> - ? ? ? ? ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
> -
> - ? ? ? ? ? ? ? /* Update secondary interrupt mask registers */
> -
> - ? ? ? ? ? ? ? /* Filter out inactive queues */
> - ? ? ? ? ? ? ? ah->ah_txq_imr_txok &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_txerr &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_txurn &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_txeol &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
> - ? ? ? ? ? ? ? ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
> -
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR0_QCU_TXOK) |
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_txdesc,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR1_QCU_TXERR) |
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_txeol,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
> - ? ? ? ? ? ? ? /* Update simr2 but don't overwrite rest simr2 settings */
> - ? ? ? ? ? ? ? AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
> - ? ? ? ? ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_txurn,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR2_QCU_TXURN));
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR3_QCBRORN) |
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR4_QTRIG), AR5K_SIMR4);
> - ? ? ? ? ? ? ? /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
> - ? ? ? ? ? ? ? ? ? ? ? AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
> - ? ? ? ? ? ? ? /* No queue has TXNOFRM enabled, disable the interrupt
> - ? ? ? ? ? ? ? ?* by setting AR5K_TXNOFRM to zero */
> - ? ? ? ? ? ? ? if (ah->ah_txq_imr_nofrm == 0)
> - ? ? ? ? ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
> -
> - ? ? ? ? ? ? ? /* Set QCU mask for this DCU to save power */
> - ? ? ? ? ? ? ? AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
> ? ? ? ?}
>
> + ? ? ? /* TODO: Handle frame compression */
> +
> + ? ? ? /*
> + ? ? ? ?* Enable interrupts for this tx queue
> + ? ? ? ?* in the secondary interrupt mask registers
> + ? ? ? ?*/
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
> +
> + ? ? ? if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
> + ? ? ? ? ? ? ? AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
> +
> + ? ? ? /* Update secondary interrupt mask registers */
> +
> + ? ? ? /* Filter out inactive queues */
> + ? ? ? ah->ah_txq_imr_txok &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_txerr &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_txurn &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_txeol &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
> + ? ? ? ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
> +
> + ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR0_QCU_TXOK) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_txdesc,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR0_QCU_TXDESC),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR0);
> +
> + ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR1_QCU_TXERR) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_txeol,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR1_QCU_TXEOL),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR1);
> +
> + ? ? ? /* Update SIMR2 but don't overwrite rest simr2 settings */
> + ? ? ? AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
> + ? ? ? AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_txurn,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR2_QCU_TXURN));
> +
> + ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR3_QCBRORN) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR3_QCBRURN),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR3);
> +
> + ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_SIMR4_QTRIG), AR5K_SIMR4);
> +
> + ? ? ? /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
> + ? ? ? ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
> +
> + ? ? ? /* No queue has TXNOFRM enabled, disable the interrupt
> + ? ? ? ?* by setting AR5K_TXNOFRM to zero */
> + ? ? ? if (ah->ah_txq_imr_nofrm == 0)
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
> +
> + ? ? ? /* Set QCU mask for this DCU to save power */
> + ? ? ? AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
> +
> ? ? ? ?return 0;
> ?}
>
> @@ -529,24 +512,114 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
> ?* Global QCU/DCU functions *
> ?\**************************/
>
> -/*
> - * Set slot time on DCU
> +/**
> + * ath5k_hw_set_ifs_intervals ?- Set global inter-frame spaces on DCU
> + *
> + * @ah The &struct ath5k_hw
> + * @slot_time Slot time in us
> + *
> + * Sets the global IFS intervals on DCU (also works on AR5210) for
> + * the given slot time and the current bwmode.
> ?*/
> -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
> +int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
> ?{
> + ? ? ? struct ieee80211_channel *channel = ah->ah_current_channel;
> + ? ? ? struct ath5k_softc *sc = ah->ah_sc;
> + ? ? ? struct ieee80211_rate *rate;
> + ? ? ? u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
> ? ? ? ?u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
>
> ? ? ? ?if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
> ? ? ? ? ? ? ? ?return -EINVAL;
>
> - ? ? ? if (ah->ah_version == AR5K_AR5210)
> + ? ? ? sifs = ath5k_hw_get_default_sifs(ah);
> + ? ? ? sifs_clock = ath5k_hw_htoclock(ah, sifs);
> +
> + ? ? ? /* EIFS
> + ? ? ? ?* Txtime of ack at lowest rate + SIFS + DIFS
> + ? ? ? ?* (DIFS = SIFS + 2 * Slot time)
> + ? ? ? ?*
> + ? ? ? ?* Note: HAL has some predefined values for EIFS
> + ? ? ? ?* Turbo: ? (37 + 2 * 6)
> + ? ? ? ?* Default: (74 + 2 * 9)
> + ? ? ? ?* Half: ? ?(149 + 2 * 13)
> + ? ? ? ?* Quarter: (298 + 2 * 21)
> + ? ? ? ?*
> + ? ? ? ?* (74 + 2 * 6) for AR5210 default and turbo !
> + ? ? ? ?*
> + ? ? ? ?* According to the formula we have
> + ? ? ? ?* ack_tx_time = 25 for turbo and
> + ? ? ? ?* ack_tx_time = 42.5 * clock multiplier
> + ? ? ? ?* for default/half/quarter.
> + ? ? ? ?*
> + ? ? ? ?* This can't be right, 42 is what we would get
> + ? ? ? ?* from ath5k_hw_get_frame_dur_for_bwmode or
> + ? ? ? ?* ieee80211_generic_frame_duration for zero frame
> + ? ? ? ?* length and without SIFS !
> + ? ? ? ?*
> + ? ? ? ?* Also we have different lowest rate for 802.11a
> + ? ? ? ?*/
> + ? ? ? if (channel->hw_value & CHANNEL_5GHZ)
> + ? ? ? ? ? ? ? rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
> + ? ? ? else
> + ? ? ? ? ? ? ? rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
> +
> + ? ? ? ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
> +
> + ? ? ? /* ack_tx_time includes an SIFS already */
> + ? ? ? eifs = ack_tx_time + sifs + 2 * slot_time;
> + ? ? ? eifs_clock = ath5k_hw_htoclock(ah, eifs);
> +
> + ? ? ? /* Set IFS settings on AR5210 */
> + ? ? ? if (ah->ah_version == AR5K_AR5210) {
> + ? ? ? ? ? ? ? u32 pifs, pifs_clock, difs, difs_clock;
> +
> + ? ? ? ? ? ? ? /* Set slot time */
> ? ? ? ? ? ? ? ?ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
> - ? ? ? else
> - ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
> +
> + ? ? ? ? ? ? ? /* Set EIFS */
> + ? ? ? ? ? ? ? eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
> +
> + ? ? ? ? ? ? ? /* PIFS = Slot time + SIFS */
> + ? ? ? ? ? ? ? pifs = slot_time + sifs;
> + ? ? ? ? ? ? ? pifs_clock = ath5k_hw_htoclock(ah, pifs);
> + ? ? ? ? ? ? ? pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
> +
> + ? ? ? ? ? ? ? /* DIFS = SIFS + 2 * Slot time */
> + ? ? ? ? ? ? ? difs = sifs + 2 * slot_time;
> + ? ? ? ? ? ? ? difs_clock = ath5k_hw_htoclock(ah, difs);
> +
> + ? ? ? ? ? ? ? /* Set SIFS/DIFS */
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, (difs_clock <<
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_IFS0_DIFS_S) | sifs_clock,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_IFS0);
> +
> + ? ? ? ? ? ? ? /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
> + ? ? ? ? ? ? ? ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_IFS1);
> +
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? }
> +
> + ? ? ? /* Set IFS slot time */
> + ? ? ? ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
> +
> + ? ? ? /* Set EIFS interval */
> + ? ? ? ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
> +
> + ? ? ? /* Set SIFS interval in usecs */
> + ? ? ? AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sifs);
> +
> + ? ? ? /* Set SIFS interval in clock cycles */
> + ? ? ? ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
>
> ? ? ? ?return 0;
> ?}
>
> +
> ?int ath5k_hw_init_queues(struct ath5k_hw *ah)
> ?{
> ? ? ? ?int i, ret;
> @@ -559,14 +632,20 @@ int ath5k_hw_init_queues(struct ath5k_hw *ah)
> ? ? ? ? * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
> ? ? ? ? * Note: If we want we can assign multiple qcus on one dcu.
> ? ? ? ? */
> - ? ? ? for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
> - ? ? ? ? ? ? ? ret = ath5k_hw_reset_tx_queue(ah, i);
> - ? ? ? ? ? ? ? if (ret) {
> - ? ? ? ? ? ? ? ? ? ? ? ATH5K_ERR(ah->ah_sc,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "failed to reset TX queue #%d\n", i);
> - ? ? ? ? ? ? ? ? ? ? ? return ret;
> + ? ? ? if (ah->ah_version != AR5K_AR5210)
> + ? ? ? ? ? ? ? for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
> + ? ? ? ? ? ? ? ? ? ? ? ret = ath5k_hw_reset_tx_queue(ah, i);
> + ? ? ? ? ? ? ? ? ? ? ? if (ret) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ATH5K_ERR(ah->ah_sc,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "failed to reset TX queue #%d\n", i);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return ret;
> + ? ? ? ? ? ? ? ? ? ? ? }
> ? ? ? ? ? ? ? ?}
> - ? ? ? }
> + ? ? ? else
> + ? ? ? ? ? ? ? /* No QCU/DCU on AR5210, just set tx
> + ? ? ? ? ? ? ? ?* retry limits. We set IFS parameters
> + ? ? ? ? ? ? ? ?* on ath5k_hw_set_ifs_intervals */
> + ? ? ? ? ? ? ? ath5k_hw_set_tx_retry_limits(ah, 0);
>
> ? ? ? ?return 0;
> ?}
> diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
> index dc213bb..8516728 100644
> --- a/drivers/net/wireless/ath/ath5k/reg.h
> +++ b/drivers/net/wireless/ath/ath5k/reg.h
> @@ -787,6 +787,7 @@
> ?#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE ? ? ? ?0x00000007 ? ? ?/* LFSR Slice Select */
> ?#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_TURBO_MODE ? ? ? ?0x00000008 ? ? ?/* Turbo mode */
> ?#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC ? ? 0x000003f0 ? ? ?/* SIFS Duration mask */
> +#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S ? 4
> ?#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_USEC_DUR ? ? ? ? ?0x000ffc00 ? ? ?/* USEC Duration mask */
> ?#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S ? ? ? ?10
> ?#define ? ? ? ?AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY ? ? 0x00300000 ? ? ?/* DCU Arbiter delay mask */
> @@ -1311,7 +1312,7 @@
> ?#define AR5K_IFS1_EIFS ? ? ? ? 0x03fff000
> ?#define AR5K_IFS1_EIFS_S ? ? ? 12
> ?#define AR5K_IFS1_CS_EN ? ? ? ? ? ? ? ?0x04000000
> -
> +#define AR5K_IFS1_CS_EN_S ? ? ?26
>
> ?/*
> ?* CFP duration register
> _______________________________________________
> ath5k-devel mailing list
> [email protected]
> https://lists.ath5k.org/mailman/listinfo/ath5k-devel
>

2010-11-24 22:41:42

by Jonathan Guerin

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

On Wed, Nov 24, 2010 at 10:55 PM, Nick Kossifidis <[email protected]> wrote:
> 2010/11/24 Jonathan Guerin <[email protected]>:
>>
>>> diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
>>> index e691378..4556f29 100644
>>> --- a/drivers/net/wireless/ath/ath5k/pcu.c
>>> +++ b/drivers/net/wireless/ath/ath5k/pcu.c
>>> @@ -763,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
>>> ?* @ah: The &struct ath5k_hw
>>> ?* @coverage_class: IEEE 802.11 coverage class number
>>> ?*
>>> - * Sets slot time, ACK timeout and CTS timeout for given coverage class.
>>> + * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
>>> ?*/
>>> ?void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>> ?{
>>> @@ -772,7 +772,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>> ? ? ? ?int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
>>
>> This is not quite right:
>>
>> According to the 802.11-2007 spec document, the ACKTimeout value is
>> (Section 9.2.8 ACK procedure):
>> ACKTimeout = aSIFSTime + aSlotTime + aPHY-RX-START-Delay
>>
>> From Table 17-15?OFDM PHY characteristics, the values are:
>> aSIFSTime = 16
>> aSlotTime = 9
>> aPHY-RX-START-Delay = 25
>>
>> Therefore, ACKTimeout = 50
>>
>> Ignoring my uniformed comments from before, this is the only thing I
>> can see that's wrong.
>>
>> Cheers,
>>
>> Jonathan
>
> Hmm I didn't mess with set_coverage_class so i didn't look up for ack
> timeout. That phy-rx-start-delay is standard value or hw specific ?
> Also does it change with clockrate (bwmodes) ? We already have a phy
> activation -> rx start delay (check patch 25). It's 10.000 on RF5111
> and 2.000 on RF5112 and later, if we divide by A clock it's 250 on
> RF5111 and 50 on RF5112 and later. Do you think it's related ?

The phy-rx-start-delay is set in the standard. I'll find you the
relevant pages soon.

I'll look up the others tomorrow. I'm feeling pretty sick today, so
not sure if I'll get a chance.

Cheers,

Jonathan

>
> --
> GPG ID: 0xD21DB2DB
> As you read this post global entropy rises. Have Fun ;-)
> Nick
>

2010-11-24 12:55:57

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

2010/11/24 Jonathan Guerin <[email protected]>:
>
>> diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
>> index e691378..4556f29 100644
>> --- a/drivers/net/wireless/ath/ath5k/pcu.c
>> +++ b/drivers/net/wireless/ath/ath5k/pcu.c
>> @@ -763,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
>>  * @ah: The &struct ath5k_hw
>>  * @coverage_class: IEEE 802.11 coverage class number
>>  *
>> - * Sets slot time, ACK timeout and CTS timeout for given coverage class.
>> + * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
>>  */
>>  void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>  {
>> @@ -772,7 +772,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>        int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
>
> This is not quite right:
>
> According to the 802.11-2007 spec document, the ACKTimeout value is
> (Section 9.2.8 ACK procedure):
> ACKTimeout = aSIFSTime + aSlotTime + aPHY-RX-START-Delay
>
> From Table 17-15—OFDM PHY characteristics, the values are:
> aSIFSTime = 16
> aSlotTime = 9
> aPHY-RX-START-Delay = 25
>
> Therefore, ACKTimeout = 50
>
> Ignoring my uniformed comments from before, this is the only thing I
> can see that's wrong.
>
> Cheers,
>
> Jonathan

Hmm I didn't mess with set_coverage_class so i didn't look up for ack
timeout. That phy-rx-start-delay is standard value or hw specific ?
Also does it change with clockrate (bwmodes) ? We already have a phy
activation -> rx start delay (check patch 25). It's 10.000 on RF5111
and 2.000 on RF5112 and later, if we divide by A clock it's 250 on
RF5111 and 50 on RF5112 and later. Do you think it's related ?

--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2010-11-27 07:36:12

by Jonathan Guerin

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

On Sat, Nov 27, 2010 at 11:57 AM, Lukáš Turek <[email protected]> wrote:
> On Saturday 27 November 2010 02:31:53 Nick Kossifidis wrote:
>> When we convert to core clock units it's what we should do, all
>> timings should change the same way. I don't know what this
>> aPHY-RX-START-Delay is but if it changes that way we can use absolute
>> values as we do for slot time and sifs.
>
> Although aPHY-RX-START-Delay is specified in the standard, it's not needed on
> Atheros hardware, probably the hardware starts the timeout countdown after it
> switches to RX mode (so aPHY-RX-START-Delay is added implicitly). See my
> discussion with Felix Fietkau a year ago, starting here:
> http://www.mail-archive.com/[email protected]/msg02810.html
>
> The calculation used in set_coverage_class is also the same as the one in
> Madwifi driver. When I wrote that code, I intentionally kept the old initvals
> when no coverage class was set to prevent regressions (the ACK timeout in
> initivals is larger than the one for coverage class 0, so a long distance link
> that worked before would break). Maybe I was too careful.

I'm going to be ashamed to admit that this is going way beyond my
understanding. You guys understand the hardware way more than I can.
Once registers don't exactly map to an 802.11 value, I'm honestly out
of my league. I hope I've helped find the correct values for
parameters that are lifted straight out of the standard, but I'm don't
want to make any comments when I don't know the full picture.

Cheers,

Jonathan
>
> Lukas Turek
>

2010-11-27 01:31:55

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 16/30] ath5k: Set all IFS intervals, not just slot time

Στις 26 Νοεμβρίου 2010 2:54 π.μ., ο χρήστης Jonathan Guerin
<[email protected]> έγραψε:
> On Thu, Nov 25, 2010 at 8:41 AM, Jonathan Guerin <[email protected]> wrote:
>> On Wed, Nov 24, 2010 at 10:55 PM, Nick Kossifidis <[email protected]> wrote:
>>> 2010/11/24 Jonathan Guerin <[email protected]>:
>>>>
>>>>> diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
>>>>> index e691378..4556f29 100644
>>>>> --- a/drivers/net/wireless/ath/ath5k/pcu.c
>>>>> +++ b/drivers/net/wireless/ath/ath5k/pcu.c
>>>>> @@ -763,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
>>>>>  * @ah: The &struct ath5k_hw
>>>>>  * @coverage_class: IEEE 802.11 coverage class number
>>>>>  *
>>>>> - * Sets slot time, ACK timeout and CTS timeout for given coverage class.
>>>>> + * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
>>>>>  */
>>>>>  void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>>>>  {
>>>>> @@ -772,7 +772,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
>>>>>        int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
>>>>
>>>> This is not quite right:
>>>>
>>>> According to the 802.11-2007 spec document, the ACKTimeout value is
>>>> (Section 9.2.8 ACK procedure):
>>>> ACKTimeout = aSIFSTime + aSlotTime + aPHY-RX-START-Delay
>>>>
>>>> From Table 17-15--OFDM PHY characteristics, the values are:
>>>> aSIFSTime = 16
>>>> aSlotTime = 9
>>>> aPHY-RX-START-Delay = 25
>>>>
>>>> Therefore, ACKTimeout = 50
>>>>
>>>> Ignoring my uniformed comments from before, this is the only thing I
>>>> can see that's wrong.
>>>>
>>>> Cheers,
>>>>
>>>> Jonathan
>>>
>>> Hmm I didn't mess with set_coverage_class so i didn't look up for ack
>>> timeout. That phy-rx-start-delay is standard value or hw specific ?
>>> Also does it change with clockrate (bwmodes) ? We already have a phy
>>> activation -> rx start delay (check patch 25). It's 10.000 on RF5111
>>> and 2.000 on RF5112 and later, if we divide by A clock it's 250 on
>>> RF5111 and 50 on RF5112 and later. Do you think it's related ?
>>
>> The phy-rx-start-delay is set in the standard. I'll find you the
>> relevant pages soon.
>
> The aPHY-RX-START-Delay value is specific per PHY. In the case of
> OFDM, you can find the relevant timings at:
>
> Table 17-15--OFDM PHY characteristics
> aPHY-RX-START-Delay 25 μs (20MHz) 49 μs (10MHz) 97 μs (5MHz)
>
>>
>> I'll look up the others tomorrow. I'm feeling pretty sick today, so
>> not sure if I'll get a chance.
>
> I just a quick look at the code. The first thing that pops to mind and
> that is apparent in the Table mentioned above, you can't just multiply
> by 2 every time you halve the channel - the value is actually slightly
> shorter than this.
>

When we convert to core clock units it's what we should do, all
timings should change the same way. I don't know what this
aPHY-RX-START-Delay is but if it changes that way we can use absolute
values as we do for slot time and sifs. Maybe we can add a function
ath5k_hw_get_default_ack_timeout that gets default sifs + default slot
time + the needed aPHY-RX-START-Delay based on the standard (but what
about turbo mode -40MHz-, do you think that using a value of 25/2
would be ok ?) and returns the total ack timeout in usecs. Or we can
do that on set_coverage_class (I prefer the first option).

> Secondly, I'm assuming that the AR5K_PHY_RX_DELAY register refers to
> the aPHY-RX-START-Delay value from the standard. It would make sense
> that the card require this value, as it is necessary in resetting the
> NAV (9.2.5.4 Setting and resetting the NAV), for CTS timeouts (9.2.5.7
> CTS procedure), & ACK Timeouts (9.2.8 ACK procedure). The first 2
> cases both refer to station behaviour after an RTS frame, but are
> slightly different in that one is from an overhearing station, whereas
> the the second is from the sending station. In the driver, which case
> is the CTSTimeout value used for?
>
> Cheers,
>
> Jonathan
>

I just remembered that this register value is in /100ns units
(according to what we have so far -check comments, remember, no
documentation on PHY registers-) so 10000 * 100ns = 1000us = 1ms for
RF5111 and 2000 * 100ns = 200us = 0.2ms for RF5112+ So it can't be
related. If it was related we (and HAL) would write this back on hw
for different bwmodes.


--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick