diff options
author | Nick Kossifidis <mick@madwifi.org> | 2009-01-06 10:27:06 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 15:59:53 -0500 |
commit | 8465676241cad5e28a1b745c32a0e18e1f67e18e (patch) | |
tree | f454dc1cbcd155d7c9d11846a09d58c72530678e /drivers/net/wireless/ath5k/qcu.c | |
parent | 8fe12920dc5fa0a0db7cad3661223d5f78a39c60 (diff) |
ath5k: Minor QCU updates
* Sync qcu.c with legacy-hal
* Add some more comments
* Set QCU mask to save power (QCU mask controls which QCUs are attached
to each DCU, we do a 1:1 mapping)
TODO: Use max QCU from EEPROM, further sync with legacy-hal and sam's
hal and a few more minor fixes.
I think after this we are ready to implement WME on the driver
part. Anyone interested ?
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/qcu.c')
-rw-r--r-- | drivers/net/wireless/ath5k/qcu.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c index 1b7bc50ea8eb..5094c394a4b2 100644 --- a/drivers/net/wireless/ath5k/qcu.c +++ b/drivers/net/wireless/ath5k/qcu.c | |||
@@ -148,6 +148,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
148 | */ | 148 | */ |
149 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | 149 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) |
150 | { | 150 | { |
151 | u32 pending; | ||
151 | ATH5K_TRACE(ah->ah_sc); | 152 | ATH5K_TRACE(ah->ah_sc); |
152 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 153 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
153 | 154 | ||
@@ -159,7 +160,15 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | |||
159 | if (ah->ah_version == AR5K_AR5210) | 160 | if (ah->ah_version == AR5K_AR5210) |
160 | return false; | 161 | return false; |
161 | 162 | ||
162 | return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT; | 163 | pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); |
164 | |||
165 | /* It's possible to have no frames pending even if TXE | ||
166 | * is set. To indicate that q has not stopped return | ||
167 | * true */ | ||
168 | if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
169 | return true; | ||
170 | |||
171 | return pending; | ||
163 | } | 172 | } |
164 | 173 | ||
165 | /* | 174 | /* |
@@ -324,8 +333,18 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
324 | /* | 333 | /* |
325 | * Set misc registers | 334 | * Set misc registers |
326 | */ | 335 | */ |
327 | ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY, | 336 | /* Enable DCU early termination for this queue */ |
328 | AR5K_QUEUE_MISC(queue)); | 337 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
338 | AR5K_QCU_MISC_DCU_EARLY); | ||
339 | |||
340 | /* Enable DCU to wait for next fragment from QCU */ | ||
341 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
342 | AR5K_DCU_MISC_FRAG_WAIT); | ||
343 | |||
344 | /* On Maui and Spirit use the global seqnum on DCU */ | ||
345 | if (ah->ah_mac_version < AR5K_SREV_AR5211) | ||
346 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
347 | AR5K_DCU_MISC_SEQNUM_CTL); | ||
329 | 348 | ||
330 | if (tq->tqi_cbr_period) { | 349 | if (tq->tqi_cbr_period) { |
331 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | 350 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, |
@@ -341,7 +360,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
341 | AR5K_QCU_MISC_CBR_THRES_ENABLE); | 360 | AR5K_QCU_MISC_CBR_THRES_ENABLE); |
342 | } | 361 | } |
343 | 362 | ||
344 | if (tq->tqi_ready_time) | 363 | if (tq->tqi_ready_time && |
364 | (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) | ||
345 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, | 365 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, |
346 | AR5K_QCU_RDYTIMECFG_INTVAL) | | 366 | AR5K_QCU_RDYTIMECFG_INTVAL) | |
347 | AR5K_QCU_RDYTIMECFG_ENABLE, | 367 | AR5K_QCU_RDYTIMECFG_ENABLE, |
@@ -383,13 +403,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
383 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | 403 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | |
384 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | 404 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | |
385 | AR5K_DCU_MISC_BCN_ENABLE); | 405 | AR5K_DCU_MISC_BCN_ENABLE); |
386 | |||
387 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
388 | (AR5K_TUNE_SW_BEACON_RESP - | ||
389 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
390 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
391 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
392 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
393 | break; | 406 | break; |
394 | 407 | ||
395 | case AR5K_TX_QUEUE_CAB: | 408 | case AR5K_TX_QUEUE_CAB: |
@@ -398,6 +411,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
398 | AR5K_QCU_MISC_CBREXP_DIS | | 411 | AR5K_QCU_MISC_CBREXP_DIS | |
399 | AR5K_QCU_MISC_CBREXP_BCN_DIS); | 412 | AR5K_QCU_MISC_CBREXP_BCN_DIS); |
400 | 413 | ||
414 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
415 | (AR5K_TUNE_SW_BEACON_RESP - | ||
416 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
417 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
418 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
419 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
420 | |||
401 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | 421 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
402 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | 422 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << |
403 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); | 423 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); |
@@ -413,6 +433,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
413 | break; | 433 | break; |
414 | } | 434 | } |
415 | 435 | ||
436 | /* TODO: Handle frame compression */ | ||
437 | |||
416 | /* | 438 | /* |
417 | * Enable interrupts for this tx queue | 439 | * Enable interrupts for this tx queue |
418 | * in the secondary interrupt mask registers | 440 | * in the secondary interrupt mask registers |
@@ -483,6 +505,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
483 | * by setting AR5K_TXNOFRM to zero */ | 505 | * by setting AR5K_TXNOFRM to zero */ |
484 | if (ah->ah_txq_imr_nofrm == 0) | 506 | if (ah->ah_txq_imr_nofrm == 0) |
485 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); | 507 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); |
508 | |||
509 | /* Set QCU mask for this DCU to save power */ | ||
510 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); | ||
486 | } | 511 | } |
487 | 512 | ||
488 | return 0; | 513 | return 0; |