aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/qcu.c
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2009-01-06 10:27:06 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 15:59:53 -0500
commit8465676241cad5e28a1b745c32a0e18e1f67e18e (patch)
treef454dc1cbcd155d7c9d11846a09d58c72530678e /drivers/net/wireless/ath5k/qcu.c
parent8fe12920dc5fa0a0db7cad3661223d5f78a39c60 (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.c47
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 */
149u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) 149u32 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;