Lines Matching +full:tx +full:- +full:queues +full:- +full:to +full:- +full:use
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
5 * Permission to use, copy, modify, and distribute this software for any
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 * Here we setup parameters for the 12 available TX queues. Note that
35 * basically we have 10 queues to play with. Each queue has a matching
37 * can be mapped to a single DCU that controls the various DFS parameters
38 * for the various queues. In our setup we have a 1:1 mapping between QCUs
39 * and DCUs allowing us to have different DFS settings for each queue.
41 * When a frame goes into a TX queue, QCU decides when it'll trigger a
43 * it's buffer or -if it's a beacon queue- if it's time to fire up the queue
47 * frames from other queues waiting to be transmitted). After a frame leaves
48 * the DCU it goes to PCU for further processing and then to PHY for
58 * ath5k_hw_num_tx_pending() - Get number of pending frames for a given queue
66 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); in ath5k_hw_num_tx_pending()
69 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) in ath5k_hw_num_tx_pending()
73 if (ah->ah_version == AR5K_AR5210) in ath5k_hw_num_tx_pending()
79 /* It's possible to have no frames pending even if TXE in ath5k_hw_num_tx_pending()
80 * is set. To indicate that q has not stopped return in ath5k_hw_num_tx_pending()
89 * ath5k_hw_release_tx_queue() - Set a transmit queue inactive
96 if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) in ath5k_hw_release_tx_queue()
100 ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; in ath5k_hw_release_tx_queue()
102 AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); in ath5k_hw_release_tx_queue()
106 * ath5k_cw_validate() - Make sure the given cw is valid
107 * @cw_req: The contention window value to check
122 return cw_req - 1; in ath5k_cw_validate()
126 cw_req = (u16) roundup_pow_of_two(cw_req) - 1; in ath5k_cw_validate()
132 * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue
135 * @queue_info: The &struct ath5k_txq_info to fill
141 memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); in ath5k_hw_get_tx_queueprops()
146 * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue
149 * @qinfo: The &struct ath5k_txq_info to use
151 * Returns 0 on success or -EIO if queue is inactive
159 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); in ath5k_hw_set_tx_queueprops()
161 qi = &ah->ah_txq[queue]; in ath5k_hw_set_tx_queueprops()
163 if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE) in ath5k_hw_set_tx_queueprops()
164 return -EIO; in ath5k_hw_set_tx_queueprops()
167 qi->tqi_type = qinfo->tqi_type; in ath5k_hw_set_tx_queueprops()
168 qi->tqi_subtype = qinfo->tqi_subtype; in ath5k_hw_set_tx_queueprops()
169 qi->tqi_flags = qinfo->tqi_flags; in ath5k_hw_set_tx_queueprops()
171 * According to the docs: Although the AIFS field is 8 bit wide, in ath5k_hw_set_tx_queueprops()
173 * will cause the DCU to hang. in ath5k_hw_set_tx_queueprops()
175 qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC); in ath5k_hw_set_tx_queueprops()
176 qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min); in ath5k_hw_set_tx_queueprops()
177 qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max); in ath5k_hw_set_tx_queueprops()
178 qi->tqi_cbr_period = qinfo->tqi_cbr_period; in ath5k_hw_set_tx_queueprops()
179 qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit; in ath5k_hw_set_tx_queueprops()
180 qi->tqi_burst_time = qinfo->tqi_burst_time; in ath5k_hw_set_tx_queueprops()
181 qi->tqi_ready_time = qinfo->tqi_ready_time; in ath5k_hw_set_tx_queueprops()
185 if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA && in ath5k_hw_set_tx_queueprops()
186 ((qinfo->tqi_subtype == AR5K_WME_AC_VI) || in ath5k_hw_set_tx_queueprops()
187 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) || in ath5k_hw_set_tx_queueprops()
188 qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD) in ath5k_hw_set_tx_queueprops()
189 qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; in ath5k_hw_set_tx_queueprops()
195 * ath5k_hw_setup_tx_queue() - Initialize a transmit queue
198 * @queue_info: The &struct ath5k_txq_info to use
200 * Returns 0 on success, -EINVAL on invalid arguments
212 /* 5210 only has 2 queues */ in ath5k_hw_setup_tx_queue()
213 if (ah->ah_capabilities.cap_queues.q_tx_num == 2) { in ath5k_hw_setup_tx_queue()
223 return -EINVAL; in ath5k_hw_setup_tx_queue()
228 queue = queue_info->tqi_subtype; in ath5k_hw_setup_tx_queue()
240 return -EINVAL; in ath5k_hw_setup_tx_queue()
247 memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); in ath5k_hw_setup_tx_queue()
248 ah->ah_txq[queue].tqi_type = queue_type; in ath5k_hw_setup_tx_queue()
251 queue_info->tqi_type = queue_type; in ath5k_hw_setup_tx_queue()
258 * We use ah_txq_status to hold a temp value for in ath5k_hw_setup_tx_queue()
262 AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); in ath5k_hw_setup_tx_queue()
273 * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU
277 * This function is used when initializing a queue, to set
278 * retry limits based on ah->ah_retry_* and the chipset used.
285 if (ah->ah_version == AR5K_AR5210) { in ath5k_hw_set_tx_retry_limits()
286 struct ath5k_txq_info *tq = &ah->ah_txq[queue]; in ath5k_hw_set_tx_retry_limits()
292 (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) in ath5k_hw_set_tx_retry_limits()
293 | AR5K_REG_SM(ah->ah_retry_long, in ath5k_hw_set_tx_retry_limits()
295 | AR5K_REG_SM(ah->ah_retry_short, in ath5k_hw_set_tx_retry_limits()
297 | AR5K_REG_SM(ah->ah_retry_long, in ath5k_hw_set_tx_retry_limits()
299 | AR5K_REG_SM(ah->ah_retry_short, in ath5k_hw_set_tx_retry_limits()
305 AR5K_REG_SM(ah->ah_retry_long, in ath5k_hw_set_tx_retry_limits()
307 | AR5K_REG_SM(ah->ah_retry_long, in ath5k_hw_set_tx_retry_limits()
309 | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short), in ath5k_hw_set_tx_retry_limits()
316 * ath5k_hw_reset_tx_queue() - Initialize a single hw queue
321 * and configures all queue-specific parameters.
326 struct ath5k_txq_info *tq = &ah->ah_txq[queue]; in ath5k_hw_reset_tx_queue()
328 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); in ath5k_hw_reset_tx_queue()
332 if ((ah->ah_version == AR5K_AR5210) || in ath5k_hw_reset_tx_queue()
333 (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)) in ath5k_hw_reset_tx_queue()
341 AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | in ath5k_hw_reset_tx_queue()
342 AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | in ath5k_hw_reset_tx_queue()
343 AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), in ath5k_hw_reset_tx_queue()
347 * Set tx retry limits for this queue in ath5k_hw_reset_tx_queue()
356 /* Enable DCU to wait for next fragment from QCU */ in ath5k_hw_reset_tx_queue()
360 /* On Maui and Spirit use the global seqnum on DCU */ in ath5k_hw_reset_tx_queue()
361 if (ah->ah_mac_version < AR5K_SREV_AR5211) in ath5k_hw_reset_tx_queue()
366 if (tq->tqi_cbr_period) { in ath5k_hw_reset_tx_queue()
367 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, in ath5k_hw_reset_tx_queue()
369 AR5K_REG_SM(tq->tqi_cbr_overflow_limit, in ath5k_hw_reset_tx_queue()
376 if (tq->tqi_cbr_overflow_limit) in ath5k_hw_reset_tx_queue()
382 if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB)) in ath5k_hw_reset_tx_queue()
383 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, in ath5k_hw_reset_tx_queue()
388 if (tq->tqi_burst_time) { in ath5k_hw_reset_tx_queue()
389 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, in ath5k_hw_reset_tx_queue()
394 if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) in ath5k_hw_reset_tx_queue()
400 if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) in ath5k_hw_reset_tx_queue()
405 if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) in ath5k_hw_reset_tx_queue()
412 switch (tq->tqi_type) { in ath5k_hw_reset_tx_queue()
428 /* XXX: use BCN_SENT_GT, if we can figure out how */ in ath5k_hw_reset_tx_queue()
434 ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - in ath5k_hw_reset_tx_queue()
435 (AR5K_TUNE_SW_BEACON_RESP - in ath5k_hw_reset_tx_queue()
436 AR5K_TUNE_DMA_BEACON_RESP) - in ath5k_hw_reset_tx_queue()
459 * Enable interrupts for this tx queue in ath5k_hw_reset_tx_queue()
462 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) in ath5k_hw_reset_tx_queue()
463 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); in ath5k_hw_reset_tx_queue()
465 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) in ath5k_hw_reset_tx_queue()
466 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); in ath5k_hw_reset_tx_queue()
468 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) in ath5k_hw_reset_tx_queue()
469 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); in ath5k_hw_reset_tx_queue()
471 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) in ath5k_hw_reset_tx_queue()
472 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); in ath5k_hw_reset_tx_queue()
474 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) in ath5k_hw_reset_tx_queue()
475 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); in ath5k_hw_reset_tx_queue()
477 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) in ath5k_hw_reset_tx_queue()
478 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); in ath5k_hw_reset_tx_queue()
480 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) in ath5k_hw_reset_tx_queue()
481 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); in ath5k_hw_reset_tx_queue()
483 if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) in ath5k_hw_reset_tx_queue()
484 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); in ath5k_hw_reset_tx_queue()
486 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) in ath5k_hw_reset_tx_queue()
487 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); in ath5k_hw_reset_tx_queue()
491 /* Filter out inactive queues */ in ath5k_hw_reset_tx_queue()
492 ah->ah_txq_imr_txok &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
493 ah->ah_txq_imr_txerr &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
494 ah->ah_txq_imr_txurn &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
495 ah->ah_txq_imr_txdesc &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
496 ah->ah_txq_imr_txeol &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
497 ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
498 ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
499 ah->ah_txq_imr_qtrig &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
500 ah->ah_txq_imr_nofrm &= ah->ah_txq_status; in ath5k_hw_reset_tx_queue()
502 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, in ath5k_hw_reset_tx_queue()
504 AR5K_REG_SM(ah->ah_txq_imr_txdesc, in ath5k_hw_reset_tx_queue()
508 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, in ath5k_hw_reset_tx_queue()
510 AR5K_REG_SM(ah->ah_txq_imr_txeol, in ath5k_hw_reset_tx_queue()
517 AR5K_REG_SM(ah->ah_txq_imr_txurn, in ath5k_hw_reset_tx_queue()
520 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, in ath5k_hw_reset_tx_queue()
522 AR5K_REG_SM(ah->ah_txq_imr_cbrurn, in ath5k_hw_reset_tx_queue()
526 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, in ath5k_hw_reset_tx_queue()
529 /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ in ath5k_hw_reset_tx_queue()
530 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, in ath5k_hw_reset_tx_queue()
534 * by setting AR5K_TXNOFRM to zero */ in ath5k_hw_reset_tx_queue()
535 if (ah->ah_txq_imr_nofrm == 0) in ath5k_hw_reset_tx_queue()
538 /* Set QCU mask for this DCU to save power */ in ath5k_hw_reset_tx_queue()
550 * ath5k_hw_set_ifs_intervals() - Set global inter-frame spaces on DCU
559 struct ieee80211_channel *channel = ah->ah_current_channel; in ath5k_hw_set_ifs_intervals()
568 return -EINVAL; in ath5k_hw_set_ifs_intervals()
571 sifs_clock = ath5k_hw_htoclock(ah, sifs - 2); in ath5k_hw_set_ifs_intervals()
585 * According to the formula we have in ath5k_hw_set_ifs_intervals()
597 if (channel->band == NL80211_BAND_5GHZ) in ath5k_hw_set_ifs_intervals()
602 switch (ah->ah_bwmode) { in ath5k_hw_set_ifs_intervals()
613 sband = &ah->sbands[band]; in ath5k_hw_set_ifs_intervals()
615 for (i = 0; i < sband->n_bitrates; i++) { in ath5k_hw_set_ifs_intervals()
616 if ((rate_flags & sband->bitrates[i].flags) != rate_flags) in ath5k_hw_set_ifs_intervals()
618 rate = &sband->bitrates[i]; in ath5k_hw_set_ifs_intervals()
622 return -EINVAL; in ath5k_hw_set_ifs_intervals()
631 if (ah->ah_version == AR5K_AR5210) { in ath5k_hw_set_ifs_intervals()
681 * ath5k_hw_init_queues() - Initialize tx queues
684 * Initializes all tx queues based on information on
685 * ah->ah_txq* set by the driver
692 /* TODO: HW Compression support for data queues */ in ath5k_hw_init_queues()
693 /* TODO: Burst prefetch for data queues */ in ath5k_hw_init_queues()
696 * Reset queues and start beacon timers at the end of the reset routine in ath5k_hw_init_queues()
697 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping in ath5k_hw_init_queues()
700 if (ah->ah_version != AR5K_AR5210) in ath5k_hw_init_queues()
701 for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { in ath5k_hw_init_queues()
705 "failed to reset TX queue #%d\n", i); in ath5k_hw_init_queues()
710 /* No QCU/DCU on AR5210, just set tx in ath5k_hw_init_queues()
716 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) in ath5k_hw_init_queues()
723 if (!ah->ah_coverage_class) { in ath5k_hw_init_queues()