linux/drivers/net/wireless/ath/ath5k/qcu.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
   3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
   4 *
   5 * Permission to use, copy, modify, and distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 *
  17 */
  18
  19/********************************************\
  20Queue Control Unit, DCF Control Unit Functions
  21\********************************************/
  22
  23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  24
  25#include "ath5k.h"
  26#include "reg.h"
  27#include "debug.h"
  28#include <linux/log2.h>
  29
  30/**
  31 * DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions
  32 *
  33 * Here we setup parameters for the 12 available TX queues. Note that
  34 * on the various registers we can usually only map the first 10 of them so
  35 * basically we have 10 queues to play with. Each queue has a matching
  36 * QCU that controls when the queue will get triggered and multiple QCUs
  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.
  40 *
  41 * When a frame goes into a TX queue, QCU decides when it'll trigger a
  42 * transmission based on various criteria (such as how many data we have inside
  43 * it's buffer or -if it's a beacon queue- if it's time to fire up the queue
  44 * based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler
  45 * (arbitrator) decides the priority of each QCU based on it's configuration
  46 * (e.g. beacons are always transmitted when they leave DCU bypassing all other
  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
  49 * the actual transmission.
  50 */
  51
  52
  53/******************\
  54* Helper functions *
  55\******************/
  56
  57/**
  58 * ath5k_hw_num_tx_pending() - Get number of pending frames for a  given queue
  59 * @ah: The &struct ath5k_hw
  60 * @queue: One of enum ath5k_tx_queue_id
  61 */
  62u32
  63ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
  64{
  65        u32 pending;
  66        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
  67
  68        /* Return if queue is declared inactive */
  69        if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
  70                return false;
  71
  72        /* XXX: How about AR5K_CFG_TXCNT ? */
  73        if (ah->ah_version == AR5K_AR5210)
  74                return false;
  75
  76        pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
  77        pending &= AR5K_QCU_STS_FRMPENDCNT;
  78
  79        /* It's possible to have no frames pending even if TXE
  80         * is set. To indicate that q has not stopped return
  81         * true */
  82        if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
  83                return true;
  84
  85        return pending;
  86}
  87
  88/**
  89 * ath5k_hw_release_tx_queue() - Set a transmit queue inactive
  90 * @ah: The &struct ath5k_hw
  91 * @queue: One of enum ath5k_tx_queue_id
  92 */
  93void
  94ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
  95{
  96        if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
  97                return;
  98
  99        /* This queue will be skipped in further operations */
 100        ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
 101        /*For SIMR setup*/
 102        AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
 103}
 104
 105/**
 106 * ath5k_cw_validate() - Make sure the given cw is valid
 107 * @cw_req: The contention window value to check
 108 *
 109 * Make sure cw is a power of 2 minus 1 and smaller than 1024
 110 */
 111static u16
 112ath5k_cw_validate(u16 cw_req)
 113{
 114        cw_req = min(cw_req, (u16)1023);
 115
 116        /* Check if cw_req + 1 a power of 2 */
 117        if (is_power_of_2(cw_req + 1))
 118                return cw_req;
 119
 120        /* Check if cw_req is a power of 2 */
 121        if (is_power_of_2(cw_req))
 122                return cw_req - 1;
 123
 124        /* If none of the above is correct
 125         * find the closest power of 2 */
 126        cw_req = (u16) roundup_pow_of_two(cw_req) - 1;
 127
 128        return cw_req;
 129}
 130
 131/**
 132 * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue
 133 * @ah: The &struct ath5k_hw
 134 * @queue: One of enum ath5k_tx_queue_id
 135 * @queue_info: The &struct ath5k_txq_info to fill
 136 */
 137int
 138ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
 139                struct ath5k_txq_info *queue_info)
 140{
 141        memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
 142        return 0;
 143}
 144
 145/**
 146 * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue
 147 * @ah: The &struct ath5k_hw
 148 * @queue: One of enum ath5k_tx_queue_id
 149 * @qinfo: The &struct ath5k_txq_info to use
 150 *
 151 * Returns 0 on success or -EIO if queue is inactive
 152 */
 153int
 154ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
 155                                const struct ath5k_txq_info *qinfo)
 156{
 157        struct ath5k_txq_info *qi;
 158
 159        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 160
 161        qi = &ah->ah_txq[queue];
 162
 163        if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
 164                return -EIO;
 165
 166        /* copy and validate values */
 167        qi->tqi_type = qinfo->tqi_type;
 168        qi->tqi_subtype = qinfo->tqi_subtype;
 169        qi->tqi_flags = qinfo->tqi_flags;
 170        /*
 171         * According to the docs: Although the AIFS field is 8 bit wide,
 172         * the maximum supported value is 0xFC. Setting it higher than that
 173         * will cause the DCU to hang.
 174         */
 175        qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
 176        qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
 177        qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
 178        qi->tqi_cbr_period = qinfo->tqi_cbr_period;
 179        qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
 180        qi->tqi_burst_time = qinfo->tqi_burst_time;
 181        qi->tqi_ready_time = qinfo->tqi_ready_time;
 182
 183        /*XXX: Is this supported on 5210 ?*/
 184        /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
 185        if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
 186                ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
 187                 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
 188             qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
 189                qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
 190
 191        return 0;
 192}
 193
 194/**
 195 * ath5k_hw_setup_tx_queue() - Initialize a transmit queue
 196 * @ah: The &struct ath5k_hw
 197 * @queue_type: One of enum ath5k_tx_queue
 198 * @queue_info: The &struct ath5k_txq_info to use
 199 *
 200 * Returns 0 on success, -EINVAL on invalid arguments
 201 */
 202int
 203ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
 204                struct ath5k_txq_info *queue_info)
 205{
 206        unsigned int queue;
 207        int ret;
 208
 209        /*
 210         * Get queue by type
 211         */
 212        /* 5210 only has 2 queues */
 213        if (ah->ah_capabilities.cap_queues.q_tx_num == 2) {
 214                switch (queue_type) {
 215                case AR5K_TX_QUEUE_DATA:
 216                        queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
 217                        break;
 218                case AR5K_TX_QUEUE_BEACON:
 219                case AR5K_TX_QUEUE_CAB:
 220                        queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
 221                        break;
 222                default:
 223                        return -EINVAL;
 224                }
 225        } else {
 226                switch (queue_type) {
 227                case AR5K_TX_QUEUE_DATA:
 228                        queue = queue_info->tqi_subtype;
 229                        break;
 230                case AR5K_TX_QUEUE_UAPSD:
 231                        queue = AR5K_TX_QUEUE_ID_UAPSD;
 232                        break;
 233                case AR5K_TX_QUEUE_BEACON:
 234                        queue = AR5K_TX_QUEUE_ID_BEACON;
 235                        break;
 236                case AR5K_TX_QUEUE_CAB:
 237                        queue = AR5K_TX_QUEUE_ID_CAB;
 238                        break;
 239                default:
 240                        return -EINVAL;
 241                }
 242        }
 243
 244        /*
 245         * Setup internal queue structure
 246         */
 247        memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
 248        ah->ah_txq[queue].tqi_type = queue_type;
 249
 250        if (queue_info != NULL) {
 251                queue_info->tqi_type = queue_type;
 252                ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
 253                if (ret)
 254                        return ret;
 255        }
 256
 257        /*
 258         * We use ah_txq_status to hold a temp value for
 259         * the Secondary interrupt mask registers on 5211+
 260         * check out ath5k_hw_reset_tx_queue
 261         */
 262        AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
 263
 264        return queue;
 265}
 266
 267
 268/*******************************\
 269* Single QCU/DCU initialization *
 270\*******************************/
 271
 272/**
 273 * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU
 274 * @ah: The &struct ath5k_hw
 275 * @queue: One of enum ath5k_tx_queue_id
 276 *
 277 * This function is used when initializing a queue, to set
 278 * retry limits based on ah->ah_retry_* and the chipset used.
 279 */
 280void
 281ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
 282                                  unsigned int queue)
 283{
 284        /* Single data queue on AR5210 */
 285        if (ah->ah_version == AR5K_AR5210) {
 286                struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 287
 288                if (queue > 0)
 289                        return;
 290
 291                ath5k_hw_reg_write(ah,
 292                        (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
 293                        | AR5K_REG_SM(ah->ah_retry_long,
 294                                      AR5K_NODCU_RETRY_LMT_SLG_RETRY)
 295                        | AR5K_REG_SM(ah->ah_retry_short,
 296                                      AR5K_NODCU_RETRY_LMT_SSH_RETRY)
 297                        | AR5K_REG_SM(ah->ah_retry_long,
 298                                      AR5K_NODCU_RETRY_LMT_LG_RETRY)
 299                        | AR5K_REG_SM(ah->ah_retry_short,
 300                                      AR5K_NODCU_RETRY_LMT_SH_RETRY),
 301                        AR5K_NODCU_RETRY_LMT);
 302        /* DCU on AR5211+ */
 303        } else {
 304                ath5k_hw_reg_write(ah,
 305                        AR5K_REG_SM(ah->ah_retry_long,
 306                                    AR5K_DCU_RETRY_LMT_RTS)
 307                        | AR5K_REG_SM(ah->ah_retry_long,
 308                                      AR5K_DCU_RETRY_LMT_STA_RTS)
 309                        | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
 310                                      AR5K_DCU_RETRY_LMT_STA_DATA),
 311                        AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
 312        }
 313}
 314
 315/**
 316 * ath5k_hw_reset_tx_queue() - Initialize a single hw queue
 317 * @ah: The &struct ath5k_hw
 318 * @queue: One of enum ath5k_tx_queue_id
 319 *
 320 * Set DCF properties for the given transmit queue on DCU
 321 * and configures all queue-specific parameters.
 322 */
 323int
 324ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
 325{
 326        struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 327
 328        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 329
 330        /* Skip if queue inactive or if we are on AR5210
 331         * that doesn't have QCU/DCU */
 332        if ((ah->ah_version == AR5K_AR5210) ||
 333        (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
 334                return 0;
 335
 336        /*
 337         * Set contention window (cw_min/cw_max)
 338         * and arbitrated interframe space (aifs)...
 339         */
 340        ath5k_hw_reg_write(ah,
 341                AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
 342                AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
 343                AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
 344                AR5K_QUEUE_DFS_LOCAL_IFS(queue));
 345
 346        /*
 347         * Set tx retry limits for this queue
 348         */
 349        ath5k_hw_set_tx_retry_limits(ah, queue);
 350
 351
 352        /*
 353         * Set misc registers
 354         */
 355
 356        /* Enable DCU to wait for next fragment from QCU */
 357        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 358                                AR5K_DCU_MISC_FRAG_WAIT);
 359
 360        /* On Maui and Spirit use the global seqnum on DCU */
 361        if (ah->ah_mac_version < AR5K_SREV_AR5211)
 362                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 363                                        AR5K_DCU_MISC_SEQNUM_CTL);
 364
 365        /* Constant bit rate period */
 366        if (tq->tqi_cbr_period) {
 367                ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
 368                                        AR5K_QCU_CBRCFG_INTVAL) |
 369                                        AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
 370                                        AR5K_QCU_CBRCFG_ORN_THRES),
 371                                        AR5K_QUEUE_CBRCFG(queue));
 372
 373                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 374                                        AR5K_QCU_MISC_FRSHED_CBR);
 375
 376                if (tq->tqi_cbr_overflow_limit)
 377                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 378                                        AR5K_QCU_MISC_CBR_THRES_ENABLE);
 379        }
 380
 381        /* Ready time interval */
 382        if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
 383                ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
 384                                        AR5K_QCU_RDYTIMECFG_INTVAL) |
 385                                        AR5K_QCU_RDYTIMECFG_ENABLE,
 386                                        AR5K_QUEUE_RDYTIMECFG(queue));
 387
 388        if (tq->tqi_burst_time) {
 389                ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
 390                                        AR5K_DCU_CHAN_TIME_DUR) |
 391                                        AR5K_DCU_CHAN_TIME_ENABLE,
 392                                        AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
 393
 394                if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
 395                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 396                                        AR5K_QCU_MISC_RDY_VEOL_POLICY);
 397        }
 398
 399        /* Enable/disable Post frame backoff */
 400        if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
 401                ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
 402                                        AR5K_QUEUE_DFS_MISC(queue));
 403
 404        /* Enable/disable fragmentation burst backoff */
 405        if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
 406                ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
 407                                        AR5K_QUEUE_DFS_MISC(queue));
 408
 409        /*
 410         * Set registers by queue type
 411         */
 412        switch (tq->tqi_type) {
 413        case AR5K_TX_QUEUE_BEACON:
 414                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 415                                AR5K_QCU_MISC_FRSHED_DBA_GT |
 416                                AR5K_QCU_MISC_CBREXP_BCN_DIS |
 417                                AR5K_QCU_MISC_BCN_ENABLE);
 418
 419                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 420                                (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
 421                                AR5K_DCU_MISC_ARBLOCK_CTL_S) |
 422                                AR5K_DCU_MISC_ARBLOCK_IGNORE |
 423                                AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
 424                                AR5K_DCU_MISC_BCN_ENABLE);
 425                break;
 426
 427        case AR5K_TX_QUEUE_CAB:
 428                /* XXX: use BCN_SENT_GT, if we can figure out how */
 429                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 430                                        AR5K_QCU_MISC_FRSHED_DBA_GT |
 431                                        AR5K_QCU_MISC_CBREXP_DIS |
 432                                        AR5K_QCU_MISC_CBREXP_BCN_DIS);
 433
 434                ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
 435                                        (AR5K_TUNE_SW_BEACON_RESP -
 436                                        AR5K_TUNE_DMA_BEACON_RESP) -
 437                                AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
 438                                        AR5K_QCU_RDYTIMECFG_ENABLE,
 439                                        AR5K_QUEUE_RDYTIMECFG(queue));
 440
 441                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 442                                        (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
 443                                        AR5K_DCU_MISC_ARBLOCK_CTL_S));
 444                break;
 445
 446        case AR5K_TX_QUEUE_UAPSD:
 447                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 448                                        AR5K_QCU_MISC_CBREXP_DIS);
 449                break;
 450
 451        case AR5K_TX_QUEUE_DATA:
 452        default:
 453                        break;
 454        }
 455
 456        /* TODO: Handle frame compression */
 457
 458        /*
 459         * Enable interrupts for this tx queue
 460         * in the secondary interrupt mask registers
 461         */
 462        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
 463                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
 464
 465        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
 466                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
 467
 468        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
 469                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
 470
 471        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
 472                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
 473
 474        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
 475                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
 476
 477        if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
 478                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
 479
 480        if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
 481                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
 482
 483        if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
 484                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
 485
 486        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
 487                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
 488
 489        /* Update secondary interrupt mask registers */
 490
 491        /* Filter out inactive queues */
 492        ah->ah_txq_imr_txok &= ah->ah_txq_status;
 493        ah->ah_txq_imr_txerr &= ah->ah_txq_status;
 494        ah->ah_txq_imr_txurn &= ah->ah_txq_status;
 495        ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
 496        ah->ah_txq_imr_txeol &= ah->ah_txq_status;
 497        ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
 498        ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
 499        ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
 500        ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
 501
 502        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
 503                                        AR5K_SIMR0_QCU_TXOK) |
 504                                        AR5K_REG_SM(ah->ah_txq_imr_txdesc,
 505                                        AR5K_SIMR0_QCU_TXDESC),
 506                                        AR5K_SIMR0);
 507
 508        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
 509                                        AR5K_SIMR1_QCU_TXERR) |
 510                                        AR5K_REG_SM(ah->ah_txq_imr_txeol,
 511                                        AR5K_SIMR1_QCU_TXEOL),
 512                                        AR5K_SIMR1);
 513
 514        /* Update SIMR2 but don't overwrite rest simr2 settings */
 515        AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
 516        AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
 517                                AR5K_REG_SM(ah->ah_txq_imr_txurn,
 518                                AR5K_SIMR2_QCU_TXURN));
 519
 520        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
 521                                AR5K_SIMR3_QCBRORN) |
 522                                AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
 523                                AR5K_SIMR3_QCBRURN),
 524                                AR5K_SIMR3);
 525
 526        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
 527                                AR5K_SIMR4_QTRIG), AR5K_SIMR4);
 528
 529        /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
 530        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
 531                                AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
 532
 533        /* No queue has TXNOFRM enabled, disable the interrupt
 534         * by setting AR5K_TXNOFRM to zero */
 535        if (ah->ah_txq_imr_nofrm == 0)
 536                ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
 537
 538        /* Set QCU mask for this DCU to save power */
 539        AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
 540
 541        return 0;
 542}
 543
 544
 545/**************************\
 546* Global QCU/DCU functions *
 547\**************************/
 548
 549/**
 550 * ath5k_hw_set_ifs_intervals()  - Set global inter-frame spaces on DCU
 551 * @ah: The &struct ath5k_hw
 552 * @slot_time: Slot time in us
 553 *
 554 * Sets the global IFS intervals on DCU (also works on AR5210) for
 555 * the given slot time and the current bwmode.
 556 */
 557int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
 558{
 559        struct ieee80211_channel *channel = ah->ah_current_channel;
 560        enum nl80211_band band;
 561        struct ieee80211_supported_band *sband;
 562        struct ieee80211_rate *rate;
 563        u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
 564        u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
 565        u32 rate_flags, i;
 566
 567        if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
 568                return -EINVAL;
 569
 570        sifs = ath5k_hw_get_default_sifs(ah);
 571        sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
 572
 573        /* EIFS
 574         * Txtime of ack at lowest rate + SIFS + DIFS
 575         * (DIFS = SIFS + 2 * Slot time)
 576         *
 577         * Note: HAL has some predefined values for EIFS
 578         * Turbo:   (37 + 2 * 6)
 579         * Default: (74 + 2 * 9)
 580         * Half:    (149 + 2 * 13)
 581         * Quarter: (298 + 2 * 21)
 582         *
 583         * (74 + 2 * 6) for AR5210 default and turbo !
 584         *
 585         * According to the formula we have
 586         * ack_tx_time = 25 for turbo and
 587         * ack_tx_time = 42.5 * clock multiplier
 588         * for default/half/quarter.
 589         *
 590         * This can't be right, 42 is what we would get
 591         * from ath5k_hw_get_frame_dur_for_bwmode or
 592         * ieee80211_generic_frame_duration for zero frame
 593         * length and without SIFS !
 594         *
 595         * Also we have different lowest rate for 802.11a
 596         */
 597        if (channel->band == NL80211_BAND_5GHZ)
 598                band = NL80211_BAND_5GHZ;
 599        else
 600                band = NL80211_BAND_2GHZ;
 601
 602        switch (ah->ah_bwmode) {
 603        case AR5K_BWMODE_5MHZ:
 604                rate_flags = IEEE80211_RATE_SUPPORTS_5MHZ;
 605                break;
 606        case AR5K_BWMODE_10MHZ:
 607                rate_flags = IEEE80211_RATE_SUPPORTS_10MHZ;
 608                break;
 609        default:
 610                rate_flags = 0;
 611                break;
 612        }
 613        sband = &ah->sbands[band];
 614        rate = NULL;
 615        for (i = 0; i < sband->n_bitrates; i++) {
 616                if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
 617                        continue;
 618                rate = &sband->bitrates[i];
 619                break;
 620        }
 621        if (WARN_ON(!rate))
 622                return -EINVAL;
 623
 624        ack_tx_time = ath5k_hw_get_frame_duration(ah, band, 10, rate, false);
 625
 626        /* ack_tx_time includes an SIFS already */
 627        eifs = ack_tx_time + sifs + 2 * slot_time;
 628        eifs_clock = ath5k_hw_htoclock(ah, eifs);
 629
 630        /* Set IFS settings on AR5210 */
 631        if (ah->ah_version == AR5K_AR5210) {
 632                u32 pifs, pifs_clock, difs, difs_clock;
 633
 634                /* Set slot time */
 635                ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
 636
 637                /* Set EIFS */
 638                eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
 639
 640                /* PIFS = Slot time + SIFS */
 641                pifs = slot_time + sifs;
 642                pifs_clock = ath5k_hw_htoclock(ah, pifs);
 643                pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
 644
 645                /* DIFS = SIFS + 2 * Slot time */
 646                difs = sifs + 2 * slot_time;
 647                difs_clock = ath5k_hw_htoclock(ah, difs);
 648
 649                /* Set SIFS/DIFS */
 650                ath5k_hw_reg_write(ah, (difs_clock <<
 651                                AR5K_IFS0_DIFS_S) | sifs_clock,
 652                                AR5K_IFS0);
 653
 654                /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
 655                ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
 656                                (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
 657                                AR5K_IFS1);
 658
 659                return 0;
 660        }
 661
 662        /* Set IFS slot time */
 663        ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
 664
 665        /* Set EIFS interval */
 666        ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
 667
 668        /* Set SIFS interval in usecs */
 669        AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
 670                                AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
 671                                sifs);
 672
 673        /* Set SIFS interval in clock cycles */
 674        ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
 675
 676        return 0;
 677}
 678
 679
 680/**
 681 * ath5k_hw_init_queues() - Initialize tx queues
 682 * @ah: The &struct ath5k_hw
 683 *
 684 * Initializes all tx queues based on information on
 685 * ah->ah_txq* set by the driver
 686 */
 687int
 688ath5k_hw_init_queues(struct ath5k_hw *ah)
 689{
 690        int i, ret;
 691
 692        /* TODO: HW Compression support for data queues */
 693        /* TODO: Burst prefetch for data queues */
 694
 695        /*
 696         * Reset queues and start beacon timers at the end of the reset routine
 697         * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
 698         * Note: If we want we can assign multiple qcus on one dcu.
 699         */
 700        if (ah->ah_version != AR5K_AR5210)
 701                for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
 702                        ret = ath5k_hw_reset_tx_queue(ah, i);
 703                        if (ret) {
 704                                ATH5K_ERR(ah,
 705                                        "failed to reset TX queue #%d\n", i);
 706                                return ret;
 707                        }
 708                }
 709        else
 710                /* No QCU/DCU on AR5210, just set tx
 711                 * retry limits. We set IFS parameters
 712                 * on ath5k_hw_set_ifs_intervals */
 713                ath5k_hw_set_tx_retry_limits(ah, 0);
 714
 715        /* Set the turbo flag when operating on 40MHz */
 716        if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
 717                AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
 718                                AR5K_DCU_GBL_IFS_MISC_TURBO_MODE);
 719
 720        /* If we didn't set IFS timings through
 721         * ath5k_hw_set_coverage_class make sure
 722         * we set them here */
 723        if (!ah->ah_coverage_class) {
 724                unsigned int slot_time = ath5k_hw_get_default_slottime(ah);
 725                ath5k_hw_set_ifs_intervals(ah, slot_time);
 726        }
 727
 728        return 0;
 729}
 730