Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
0003  * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
0004  *
0005  * Permission to use, copy, modify, and distribute this software for any
0006  * purpose with or without fee is hereby granted, provided that the above
0007  * copyright notice and this permission notice appear in all copies.
0008  *
0009  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0010  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0011  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0012  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0015  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0016  *
0017  */
0018 
0019 /********************************************\
0020 Queue Control Unit, DCF Control Unit Functions
0021 \********************************************/
0022 
0023 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0024 
0025 #include "ath5k.h"
0026 #include "reg.h"
0027 #include "debug.h"
0028 #include <linux/log2.h>
0029 
0030 /**
0031  * DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions
0032  *
0033  * Here we setup parameters for the 12 available TX queues. Note that
0034  * on the various registers we can usually only map the first 10 of them so
0035  * basically we have 10 queues to play with. Each queue has a matching
0036  * QCU that controls when the queue will get triggered and multiple QCUs
0037  * can be mapped to a single DCU that controls the various DFS parameters
0038  * for the various queues. In our setup we have a 1:1 mapping between QCUs
0039  * and DCUs allowing us to have different DFS settings for each queue.
0040  *
0041  * When a frame goes into a TX queue, QCU decides when it'll trigger a
0042  * transmission based on various criteria (such as how many data we have inside
0043  * it's buffer or -if it's a beacon queue- if it's time to fire up the queue
0044  * based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler
0045  * (arbitrator) decides the priority of each QCU based on it's configuration
0046  * (e.g. beacons are always transmitted when they leave DCU bypassing all other
0047  * frames from other queues waiting to be transmitted). After a frame leaves
0048  * the DCU it goes to PCU for further processing and then to PHY for
0049  * the actual transmission.
0050  */
0051 
0052 
0053 /******************\
0054 * Helper functions *
0055 \******************/
0056 
0057 /**
0058  * ath5k_hw_num_tx_pending() - Get number of pending frames for a  given queue
0059  * @ah: The &struct ath5k_hw
0060  * @queue: One of enum ath5k_tx_queue_id
0061  */
0062 u32
0063 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
0064 {
0065     u32 pending;
0066     AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
0067 
0068     /* Return if queue is declared inactive */
0069     if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
0070         return false;
0071 
0072     /* XXX: How about AR5K_CFG_TXCNT ? */
0073     if (ah->ah_version == AR5K_AR5210)
0074         return false;
0075 
0076     pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
0077     pending &= AR5K_QCU_STS_FRMPENDCNT;
0078 
0079     /* It's possible to have no frames pending even if TXE
0080      * is set. To indicate that q has not stopped return
0081      * true */
0082     if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
0083         return true;
0084 
0085     return pending;
0086 }
0087 
0088 /**
0089  * ath5k_hw_release_tx_queue() - Set a transmit queue inactive
0090  * @ah: The &struct ath5k_hw
0091  * @queue: One of enum ath5k_tx_queue_id
0092  */
0093 void
0094 ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
0095 {
0096     if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
0097         return;
0098 
0099     /* This queue will be skipped in further operations */
0100     ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
0101     /*For SIMR setup*/
0102     AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
0103 }
0104 
0105 /**
0106  * ath5k_cw_validate() - Make sure the given cw is valid
0107  * @cw_req: The contention window value to check
0108  *
0109  * Make sure cw is a power of 2 minus 1 and smaller than 1024
0110  */
0111 static u16
0112 ath5k_cw_validate(u16 cw_req)
0113 {
0114     cw_req = min(cw_req, (u16)1023);
0115 
0116     /* Check if cw_req + 1 a power of 2 */
0117     if (is_power_of_2(cw_req + 1))
0118         return cw_req;
0119 
0120     /* Check if cw_req is a power of 2 */
0121     if (is_power_of_2(cw_req))
0122         return cw_req - 1;
0123 
0124     /* If none of the above is correct
0125      * find the closest power of 2 */
0126     cw_req = (u16) roundup_pow_of_two(cw_req) - 1;
0127 
0128     return cw_req;
0129 }
0130 
0131 /**
0132  * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue
0133  * @ah: The &struct ath5k_hw
0134  * @queue: One of enum ath5k_tx_queue_id
0135  * @queue_info: The &struct ath5k_txq_info to fill
0136  */
0137 int
0138 ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
0139         struct ath5k_txq_info *queue_info)
0140 {
0141     memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
0142     return 0;
0143 }
0144 
0145 /**
0146  * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue
0147  * @ah: The &struct ath5k_hw
0148  * @queue: One of enum ath5k_tx_queue_id
0149  * @qinfo: The &struct ath5k_txq_info to use
0150  *
0151  * Returns 0 on success or -EIO if queue is inactive
0152  */
0153 int
0154 ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
0155                 const struct ath5k_txq_info *qinfo)
0156 {
0157     struct ath5k_txq_info *qi;
0158 
0159     AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
0160 
0161     qi = &ah->ah_txq[queue];
0162 
0163     if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
0164         return -EIO;
0165 
0166     /* copy and validate values */
0167     qi->tqi_type = qinfo->tqi_type;
0168     qi->tqi_subtype = qinfo->tqi_subtype;
0169     qi->tqi_flags = qinfo->tqi_flags;
0170     /*
0171      * According to the docs: Although the AIFS field is 8 bit wide,
0172      * the maximum supported value is 0xFC. Setting it higher than that
0173      * will cause the DCU to hang.
0174      */
0175     qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
0176     qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
0177     qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
0178     qi->tqi_cbr_period = qinfo->tqi_cbr_period;
0179     qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
0180     qi->tqi_burst_time = qinfo->tqi_burst_time;
0181     qi->tqi_ready_time = qinfo->tqi_ready_time;
0182 
0183     /*XXX: Is this supported on 5210 ?*/
0184     /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
0185     if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
0186         ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
0187          (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
0188          qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
0189         qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
0190 
0191     return 0;
0192 }
0193 
0194 /**
0195  * ath5k_hw_setup_tx_queue() - Initialize a transmit queue
0196  * @ah: The &struct ath5k_hw
0197  * @queue_type: One of enum ath5k_tx_queue
0198  * @queue_info: The &struct ath5k_txq_info to use
0199  *
0200  * Returns 0 on success, -EINVAL on invalid arguments
0201  */
0202 int
0203 ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
0204         struct ath5k_txq_info *queue_info)
0205 {
0206     unsigned int queue;
0207     int ret;
0208 
0209     /*
0210      * Get queue by type
0211      */
0212     /* 5210 only has 2 queues */
0213     if (ah->ah_capabilities.cap_queues.q_tx_num == 2) {
0214         switch (queue_type) {
0215         case AR5K_TX_QUEUE_DATA:
0216             queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
0217             break;
0218         case AR5K_TX_QUEUE_BEACON:
0219         case AR5K_TX_QUEUE_CAB:
0220             queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
0221             break;
0222         default:
0223             return -EINVAL;
0224         }
0225     } else {
0226         switch (queue_type) {
0227         case AR5K_TX_QUEUE_DATA:
0228             queue = queue_info->tqi_subtype;
0229             break;
0230         case AR5K_TX_QUEUE_UAPSD:
0231             queue = AR5K_TX_QUEUE_ID_UAPSD;
0232             break;
0233         case AR5K_TX_QUEUE_BEACON:
0234             queue = AR5K_TX_QUEUE_ID_BEACON;
0235             break;
0236         case AR5K_TX_QUEUE_CAB:
0237             queue = AR5K_TX_QUEUE_ID_CAB;
0238             break;
0239         default:
0240             return -EINVAL;
0241         }
0242     }
0243 
0244     /*
0245      * Setup internal queue structure
0246      */
0247     memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
0248     ah->ah_txq[queue].tqi_type = queue_type;
0249 
0250     if (queue_info != NULL) {
0251         queue_info->tqi_type = queue_type;
0252         ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
0253         if (ret)
0254             return ret;
0255     }
0256 
0257     /*
0258      * We use ah_txq_status to hold a temp value for
0259      * the Secondary interrupt mask registers on 5211+
0260      * check out ath5k_hw_reset_tx_queue
0261      */
0262     AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
0263 
0264     return queue;
0265 }
0266 
0267 
0268 /*******************************\
0269 * Single QCU/DCU initialization *
0270 \*******************************/
0271 
0272 /**
0273  * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU
0274  * @ah: The &struct ath5k_hw
0275  * @queue: One of enum ath5k_tx_queue_id
0276  *
0277  * This function is used when initializing a queue, to set
0278  * retry limits based on ah->ah_retry_* and the chipset used.
0279  */
0280 void
0281 ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
0282                   unsigned int queue)
0283 {
0284     /* Single data queue on AR5210 */
0285     if (ah->ah_version == AR5K_AR5210) {
0286         struct ath5k_txq_info *tq = &ah->ah_txq[queue];
0287 
0288         if (queue > 0)
0289             return;
0290 
0291         ath5k_hw_reg_write(ah,
0292             (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
0293             | AR5K_REG_SM(ah->ah_retry_long,
0294                       AR5K_NODCU_RETRY_LMT_SLG_RETRY)
0295             | AR5K_REG_SM(ah->ah_retry_short,
0296                       AR5K_NODCU_RETRY_LMT_SSH_RETRY)
0297             | AR5K_REG_SM(ah->ah_retry_long,
0298                       AR5K_NODCU_RETRY_LMT_LG_RETRY)
0299             | AR5K_REG_SM(ah->ah_retry_short,
0300                       AR5K_NODCU_RETRY_LMT_SH_RETRY),
0301             AR5K_NODCU_RETRY_LMT);
0302     /* DCU on AR5211+ */
0303     } else {
0304         ath5k_hw_reg_write(ah,
0305             AR5K_REG_SM(ah->ah_retry_long,
0306                     AR5K_DCU_RETRY_LMT_RTS)
0307             | AR5K_REG_SM(ah->ah_retry_long,
0308                       AR5K_DCU_RETRY_LMT_STA_RTS)
0309             | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
0310                       AR5K_DCU_RETRY_LMT_STA_DATA),
0311             AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
0312     }
0313 }
0314 
0315 /**
0316  * ath5k_hw_reset_tx_queue() - Initialize a single hw queue
0317  * @ah: The &struct ath5k_hw
0318  * @queue: One of enum ath5k_tx_queue_id
0319  *
0320  * Set DCF properties for the given transmit queue on DCU
0321  * and configures all queue-specific parameters.
0322  */
0323 int
0324 ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
0325 {
0326     struct ath5k_txq_info *tq = &ah->ah_txq[queue];
0327 
0328     AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
0329 
0330     /* Skip if queue inactive or if we are on AR5210
0331      * that doesn't have QCU/DCU */
0332     if ((ah->ah_version == AR5K_AR5210) ||
0333     (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
0334         return 0;
0335 
0336     /*
0337      * Set contention window (cw_min/cw_max)
0338      * and arbitrated interframe space (aifs)...
0339      */
0340     ath5k_hw_reg_write(ah,
0341         AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
0342         AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
0343         AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
0344         AR5K_QUEUE_DFS_LOCAL_IFS(queue));
0345 
0346     /*
0347      * Set tx retry limits for this queue
0348      */
0349     ath5k_hw_set_tx_retry_limits(ah, queue);
0350 
0351 
0352     /*
0353      * Set misc registers
0354      */
0355 
0356     /* Enable DCU to wait for next fragment from QCU */
0357     AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
0358                 AR5K_DCU_MISC_FRAG_WAIT);
0359 
0360     /* On Maui and Spirit use the global seqnum on DCU */
0361     if (ah->ah_mac_version < AR5K_SREV_AR5211)
0362         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
0363                     AR5K_DCU_MISC_SEQNUM_CTL);
0364 
0365     /* Constant bit rate period */
0366     if (tq->tqi_cbr_period) {
0367         ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
0368                     AR5K_QCU_CBRCFG_INTVAL) |
0369                     AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
0370                     AR5K_QCU_CBRCFG_ORN_THRES),
0371                     AR5K_QUEUE_CBRCFG(queue));
0372 
0373         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
0374                     AR5K_QCU_MISC_FRSHED_CBR);
0375 
0376         if (tq->tqi_cbr_overflow_limit)
0377             AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
0378                     AR5K_QCU_MISC_CBR_THRES_ENABLE);
0379     }
0380 
0381     /* Ready time interval */
0382     if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
0383         ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
0384                     AR5K_QCU_RDYTIMECFG_INTVAL) |
0385                     AR5K_QCU_RDYTIMECFG_ENABLE,
0386                     AR5K_QUEUE_RDYTIMECFG(queue));
0387 
0388     if (tq->tqi_burst_time) {
0389         ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
0390                     AR5K_DCU_CHAN_TIME_DUR) |
0391                     AR5K_DCU_CHAN_TIME_ENABLE,
0392                     AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
0393 
0394         if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
0395             AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
0396                     AR5K_QCU_MISC_RDY_VEOL_POLICY);
0397     }
0398 
0399     /* Enable/disable Post frame backoff */
0400     if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
0401         ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
0402                     AR5K_QUEUE_DFS_MISC(queue));
0403 
0404     /* Enable/disable fragmentation burst backoff */
0405     if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
0406         ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
0407                     AR5K_QUEUE_DFS_MISC(queue));
0408 
0409     /*
0410      * Set registers by queue type
0411      */
0412     switch (tq->tqi_type) {
0413     case AR5K_TX_QUEUE_BEACON:
0414         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
0415                 AR5K_QCU_MISC_FRSHED_DBA_GT |
0416                 AR5K_QCU_MISC_CBREXP_BCN_DIS |
0417                 AR5K_QCU_MISC_BCN_ENABLE);
0418 
0419         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
0420                 (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
0421                 AR5K_DCU_MISC_ARBLOCK_CTL_S) |
0422                 AR5K_DCU_MISC_ARBLOCK_IGNORE |
0423                 AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
0424                 AR5K_DCU_MISC_BCN_ENABLE);
0425         break;
0426 
0427     case AR5K_TX_QUEUE_CAB:
0428         /* XXX: use BCN_SENT_GT, if we can figure out how */
0429         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
0430                     AR5K_QCU_MISC_FRSHED_DBA_GT |
0431                     AR5K_QCU_MISC_CBREXP_DIS |
0432                     AR5K_QCU_MISC_CBREXP_BCN_DIS);
0433 
0434         ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
0435                     (AR5K_TUNE_SW_BEACON_RESP -
0436                     AR5K_TUNE_DMA_BEACON_RESP) -
0437                 AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
0438                     AR5K_QCU_RDYTIMECFG_ENABLE,
0439                     AR5K_QUEUE_RDYTIMECFG(queue));
0440 
0441         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
0442                     (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
0443                     AR5K_DCU_MISC_ARBLOCK_CTL_S));
0444         break;
0445 
0446     case AR5K_TX_QUEUE_UAPSD:
0447         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
0448                     AR5K_QCU_MISC_CBREXP_DIS);
0449         break;
0450 
0451     case AR5K_TX_QUEUE_DATA:
0452     default:
0453             break;
0454     }
0455 
0456     /* TODO: Handle frame compression */
0457 
0458     /*
0459      * Enable interrupts for this tx queue
0460      * in the secondary interrupt mask registers
0461      */
0462     if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
0463         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
0464 
0465     if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
0466         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
0467 
0468     if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
0469         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
0470 
0471     if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
0472         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
0473 
0474     if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
0475         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
0476 
0477     if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
0478         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
0479 
0480     if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
0481         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
0482 
0483     if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
0484         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
0485 
0486     if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
0487         AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
0488 
0489     /* Update secondary interrupt mask registers */
0490 
0491     /* Filter out inactive queues */
0492     ah->ah_txq_imr_txok &= ah->ah_txq_status;
0493     ah->ah_txq_imr_txerr &= ah->ah_txq_status;
0494     ah->ah_txq_imr_txurn &= ah->ah_txq_status;
0495     ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
0496     ah->ah_txq_imr_txeol &= ah->ah_txq_status;
0497     ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
0498     ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
0499     ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
0500     ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
0501 
0502     ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
0503                     AR5K_SIMR0_QCU_TXOK) |
0504                     AR5K_REG_SM(ah->ah_txq_imr_txdesc,
0505                     AR5K_SIMR0_QCU_TXDESC),
0506                     AR5K_SIMR0);
0507 
0508     ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
0509                     AR5K_SIMR1_QCU_TXERR) |
0510                     AR5K_REG_SM(ah->ah_txq_imr_txeol,
0511                     AR5K_SIMR1_QCU_TXEOL),
0512                     AR5K_SIMR1);
0513 
0514     /* Update SIMR2 but don't overwrite rest simr2 settings */
0515     AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
0516     AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
0517                 AR5K_REG_SM(ah->ah_txq_imr_txurn,
0518                 AR5K_SIMR2_QCU_TXURN));
0519 
0520     ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
0521                 AR5K_SIMR3_QCBRORN) |
0522                 AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
0523                 AR5K_SIMR3_QCBRURN),
0524                 AR5K_SIMR3);
0525 
0526     ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
0527                 AR5K_SIMR4_QTRIG), AR5K_SIMR4);
0528 
0529     /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
0530     ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
0531                 AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
0532 
0533     /* No queue has TXNOFRM enabled, disable the interrupt
0534      * by setting AR5K_TXNOFRM to zero */
0535     if (ah->ah_txq_imr_nofrm == 0)
0536         ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
0537 
0538     /* Set QCU mask for this DCU to save power */
0539     AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
0540 
0541     return 0;
0542 }
0543 
0544 
0545 /**************************\
0546 * Global QCU/DCU functions *
0547 \**************************/
0548 
0549 /**
0550  * ath5k_hw_set_ifs_intervals()  - Set global inter-frame spaces on DCU
0551  * @ah: The &struct ath5k_hw
0552  * @slot_time: Slot time in us
0553  *
0554  * Sets the global IFS intervals on DCU (also works on AR5210) for
0555  * the given slot time and the current bwmode.
0556  */
0557 int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
0558 {
0559     struct ieee80211_channel *channel = ah->ah_current_channel;
0560     enum nl80211_band band;
0561     struct ieee80211_supported_band *sband;
0562     struct ieee80211_rate *rate;
0563     u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
0564     u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
0565     u32 rate_flags, i;
0566 
0567     if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
0568         return -EINVAL;
0569 
0570     sifs = ath5k_hw_get_default_sifs(ah);
0571     sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
0572 
0573     /* EIFS
0574      * Txtime of ack at lowest rate + SIFS + DIFS
0575      * (DIFS = SIFS + 2 * Slot time)
0576      *
0577      * Note: HAL has some predefined values for EIFS
0578      * Turbo:   (37 + 2 * 6)
0579      * Default: (74 + 2 * 9)
0580      * Half:    (149 + 2 * 13)
0581      * Quarter: (298 + 2 * 21)
0582      *
0583      * (74 + 2 * 6) for AR5210 default and turbo !
0584      *
0585      * According to the formula we have
0586      * ack_tx_time = 25 for turbo and
0587      * ack_tx_time = 42.5 * clock multiplier
0588      * for default/half/quarter.
0589      *
0590      * This can't be right, 42 is what we would get
0591      * from ath5k_hw_get_frame_dur_for_bwmode or
0592      * ieee80211_generic_frame_duration for zero frame
0593      * length and without SIFS !
0594      *
0595      * Also we have different lowest rate for 802.11a
0596      */
0597     if (channel->band == NL80211_BAND_5GHZ)
0598         band = NL80211_BAND_5GHZ;
0599     else
0600         band = NL80211_BAND_2GHZ;
0601 
0602     switch (ah->ah_bwmode) {
0603     case AR5K_BWMODE_5MHZ:
0604         rate_flags = IEEE80211_RATE_SUPPORTS_5MHZ;
0605         break;
0606     case AR5K_BWMODE_10MHZ:
0607         rate_flags = IEEE80211_RATE_SUPPORTS_10MHZ;
0608         break;
0609     default:
0610         rate_flags = 0;
0611         break;
0612     }
0613     sband = &ah->sbands[band];
0614     rate = NULL;
0615     for (i = 0; i < sband->n_bitrates; i++) {
0616         if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
0617             continue;
0618         rate = &sband->bitrates[i];
0619         break;
0620     }
0621     if (WARN_ON(!rate))
0622         return -EINVAL;
0623 
0624     ack_tx_time = ath5k_hw_get_frame_duration(ah, band, 10, rate, false);
0625 
0626     /* ack_tx_time includes an SIFS already */
0627     eifs = ack_tx_time + sifs + 2 * slot_time;
0628     eifs_clock = ath5k_hw_htoclock(ah, eifs);
0629 
0630     /* Set IFS settings on AR5210 */
0631     if (ah->ah_version == AR5K_AR5210) {
0632         u32 pifs, pifs_clock, difs, difs_clock;
0633 
0634         /* Set slot time */
0635         ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
0636 
0637         /* Set EIFS */
0638         eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
0639 
0640         /* PIFS = Slot time + SIFS */
0641         pifs = slot_time + sifs;
0642         pifs_clock = ath5k_hw_htoclock(ah, pifs);
0643         pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
0644 
0645         /* DIFS = SIFS + 2 * Slot time */
0646         difs = sifs + 2 * slot_time;
0647         difs_clock = ath5k_hw_htoclock(ah, difs);
0648 
0649         /* Set SIFS/DIFS */
0650         ath5k_hw_reg_write(ah, (difs_clock <<
0651                 AR5K_IFS0_DIFS_S) | sifs_clock,
0652                 AR5K_IFS0);
0653 
0654         /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
0655         ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
0656                 (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
0657                 AR5K_IFS1);
0658 
0659         return 0;
0660     }
0661 
0662     /* Set IFS slot time */
0663     ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
0664 
0665     /* Set EIFS interval */
0666     ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
0667 
0668     /* Set SIFS interval in usecs */
0669     AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
0670                 AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
0671                 sifs);
0672 
0673     /* Set SIFS interval in clock cycles */
0674     ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
0675 
0676     return 0;
0677 }
0678 
0679 
0680 /**
0681  * ath5k_hw_init_queues() - Initialize tx queues
0682  * @ah: The &struct ath5k_hw
0683  *
0684  * Initializes all tx queues based on information on
0685  * ah->ah_txq* set by the driver
0686  */
0687 int
0688 ath5k_hw_init_queues(struct ath5k_hw *ah)
0689 {
0690     int i, ret;
0691 
0692     /* TODO: HW Compression support for data queues */
0693     /* TODO: Burst prefetch for data queues */
0694 
0695     /*
0696      * Reset queues and start beacon timers at the end of the reset routine
0697      * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
0698      * Note: If we want we can assign multiple qcus on one dcu.
0699      */
0700     if (ah->ah_version != AR5K_AR5210)
0701         for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
0702             ret = ath5k_hw_reset_tx_queue(ah, i);
0703             if (ret) {
0704                 ATH5K_ERR(ah,
0705                     "failed to reset TX queue #%d\n", i);
0706                 return ret;
0707             }
0708         }
0709     else
0710         /* No QCU/DCU on AR5210, just set tx
0711          * retry limits. We set IFS parameters
0712          * on ath5k_hw_set_ifs_intervals */
0713         ath5k_hw_set_tx_retry_limits(ah, 0);
0714 
0715     /* Set the turbo flag when operating on 40MHz */
0716     if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
0717         AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
0718                 AR5K_DCU_GBL_IFS_MISC_TURBO_MODE);
0719 
0720     /* If we didn't set IFS timings through
0721      * ath5k_hw_set_coverage_class make sure
0722      * we set them here */
0723     if (!ah->ah_coverage_class) {
0724         unsigned int slot_time = ath5k_hw_get_default_slottime(ah);
0725         ath5k_hw_set_ifs_intervals(ah, slot_time);
0726     }
0727 
0728     return 0;
0729 }