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, DFS Control Unit Functions
  21\********************************************/
  22
  23#include "ath5k.h"
  24#include "reg.h"
  25#include "debug.h"
  26#include "base.h"
  27
  28
  29/******************\
  30* Helper functions *
  31\******************/
  32
  33/*
  34 * Get number of pending frames
  35 * for a specific queue [5211+]
  36 */
  37u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
  38{
  39        u32 pending;
  40        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
  41
  42        /* Return if queue is declared inactive */
  43        if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
  44                return false;
  45
  46        /* XXX: How about AR5K_CFG_TXCNT ? */
  47        if (ah->ah_version == AR5K_AR5210)
  48                return false;
  49
  50        pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
  51        pending &= AR5K_QCU_STS_FRMPENDCNT;
  52
  53        /* It's possible to have no frames pending even if TXE
  54         * is set. To indicate that q has not stopped return
  55         * true */
  56        if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
  57                return true;
  58
  59        return pending;
  60}
  61
  62/*
  63 * Set a transmit queue inactive
  64 */
  65void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
  66{
  67        if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
  68                return;
  69
  70        /* This queue will be skipped in further operations */
  71        ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
  72        /*For SIMR setup*/
  73        AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
  74}
  75
  76/*
  77 * Make sure cw is a power of 2 minus 1 and smaller than 1024
  78 */
  79static u16 ath5k_cw_validate(u16 cw_req)
  80{
  81        u32 cw = 1;
  82        cw_req = min(cw_req, (u16)1023);
  83
  84        while (cw < cw_req)
  85                cw = (cw << 1) | 1;
  86
  87        return cw;
  88}
  89
  90/*
  91 * Get properties for a transmit queue
  92 */
  93int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
  94                struct ath5k_txq_info *queue_info)
  95{
  96        memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
  97        return 0;
  98}
  99
 100/*
 101 * Set properties for a transmit queue
 102 */
 103int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
 104                                const struct ath5k_txq_info *qinfo)
 105{
 106        struct ath5k_txq_info *qi;
 107
 108        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 109
 110        qi = &ah->ah_txq[queue];
 111
 112        if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
 113                return -EIO;
 114
 115        /* copy and validate values */
 116        qi->tqi_type = qinfo->tqi_type;
 117        qi->tqi_subtype = qinfo->tqi_subtype;
 118        qi->tqi_flags = qinfo->tqi_flags;
 119        /*
 120         * According to the docs: Although the AIFS field is 8 bit wide,
 121         * the maximum supported value is 0xFC. Setting it higher than that
 122         * will cause the DCU to hang.
 123         */
 124        qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
 125        qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
 126        qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
 127        qi->tqi_cbr_period = qinfo->tqi_cbr_period;
 128        qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
 129        qi->tqi_burst_time = qinfo->tqi_burst_time;
 130        qi->tqi_ready_time = qinfo->tqi_ready_time;
 131
 132        /*XXX: Is this supported on 5210 ?*/
 133        /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
 134        if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
 135                ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
 136                 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
 137             qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
 138                qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
 139
 140        return 0;
 141}
 142
 143/*
 144 * Initialize a transmit queue
 145 */
 146int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
 147                struct ath5k_txq_info *queue_info)
 148{
 149        unsigned int queue;
 150        int ret;
 151
 152        /*
 153         * Get queue by type
 154         */
 155        /* 5210 only has 2 queues */
 156        if (ah->ah_capabilities.cap_queues.q_tx_num == 2) {
 157                switch (queue_type) {
 158                case AR5K_TX_QUEUE_DATA:
 159                        queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
 160                        break;
 161                case AR5K_TX_QUEUE_BEACON:
 162                case AR5K_TX_QUEUE_CAB:
 163                        queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
 164                        break;
 165                default:
 166                        return -EINVAL;
 167                }
 168        } else {
 169                switch (queue_type) {
 170                case AR5K_TX_QUEUE_DATA:
 171                        for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
 172                                ah->ah_txq[queue].tqi_type !=
 173                                AR5K_TX_QUEUE_INACTIVE; queue++) {
 174
 175                                if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
 176                                        return -EINVAL;
 177                        }
 178                        break;
 179                case AR5K_TX_QUEUE_UAPSD:
 180                        queue = AR5K_TX_QUEUE_ID_UAPSD;
 181                        break;
 182                case AR5K_TX_QUEUE_BEACON:
 183                        queue = AR5K_TX_QUEUE_ID_BEACON;
 184                        break;
 185                case AR5K_TX_QUEUE_CAB:
 186                        queue = AR5K_TX_QUEUE_ID_CAB;
 187                        break;
 188                case AR5K_TX_QUEUE_XR_DATA:
 189                        if (ah->ah_version != AR5K_AR5212)
 190                                ATH5K_ERR(ah->ah_sc,
 191                                        "XR data queues only supported in"
 192                                        " 5212!\n");
 193                        queue = AR5K_TX_QUEUE_ID_XR_DATA;
 194                        break;
 195                default:
 196                        return -EINVAL;
 197                }
 198        }
 199
 200        /*
 201         * Setup internal queue structure
 202         */
 203        memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
 204        ah->ah_txq[queue].tqi_type = queue_type;
 205
 206        if (queue_info != NULL) {
 207                queue_info->tqi_type = queue_type;
 208                ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
 209                if (ret)
 210                        return ret;
 211        }
 212
 213        /*
 214         * We use ah_txq_status to hold a temp value for
 215         * the Secondary interrupt mask registers on 5211+
 216         * check out ath5k_hw_reset_tx_queue
 217         */
 218        AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
 219
 220        return queue;
 221}
 222
 223
 224/*******************************\
 225* Single QCU/DCU initialization *
 226\*******************************/
 227
 228/*
 229 * Set tx retry limits on DCU
 230 */
 231static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
 232                                        unsigned int queue)
 233{
 234        u32 retry_lg, retry_sh;
 235
 236        /*
 237         * Calculate and set retry limits
 238         */
 239        if (ah->ah_software_retry) {
 240                /* XXX Need to test this */
 241                retry_lg = ah->ah_limit_tx_retries;
 242                retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
 243                        AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
 244        } else {
 245                retry_lg = AR5K_INIT_LG_RETRY;
 246                retry_sh = AR5K_INIT_SH_RETRY;
 247        }
 248
 249        /* Single data queue on AR5210 */
 250        if (ah->ah_version == AR5K_AR5210) {
 251                struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 252
 253                if (queue > 0)
 254                        return;
 255
 256                ath5k_hw_reg_write(ah,
 257                        (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
 258                        | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
 259                                AR5K_NODCU_RETRY_LMT_SLG_RETRY)
 260                        | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
 261                                AR5K_NODCU_RETRY_LMT_SSH_RETRY)
 262                        | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
 263                        | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
 264                        AR5K_NODCU_RETRY_LMT);
 265        /* DCU on AR5211+ */
 266        } else {
 267                ath5k_hw_reg_write(ah,
 268                        AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
 269                                AR5K_DCU_RETRY_LMT_SLG_RETRY) |
 270                        AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
 271                                AR5K_DCU_RETRY_LMT_SSH_RETRY) |
 272                        AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
 273                        AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
 274                        AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
 275        }
 276        return;
 277}
 278
 279/**
 280 * ath5k_hw_reset_tx_queue - Initialize a single hw queue
 281 *
 282 * @ah The &struct ath5k_hw
 283 * @queue The hw queue number
 284 *
 285 * Set DFS properties for the given transmit queue on DCU
 286 * and configures all queue-specific parameters.
 287 */
 288int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
 289{
 290        struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 291
 292        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 293
 294        tq = &ah->ah_txq[queue];
 295
 296        /* Skip if queue inactive or if we are on AR5210
 297         * that doesn't have QCU/DCU */
 298        if ((ah->ah_version == AR5K_AR5210) ||
 299        (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
 300                return 0;
 301
 302        /*
 303         * Set contention window (cw_min/cw_max)
 304         * and arbitrated interframe space (aifs)...
 305         */
 306        ath5k_hw_reg_write(ah,
 307                AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
 308                AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
 309                AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
 310                AR5K_QUEUE_DFS_LOCAL_IFS(queue));
 311
 312        /*
 313         * Set tx retry limits for this queue
 314         */
 315        ath5k_hw_set_tx_retry_limits(ah, queue);
 316
 317
 318        /*
 319         * Set misc registers
 320         */
 321
 322        /* Enable DCU to wait for next fragment from QCU */
 323        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 324                                AR5K_DCU_MISC_FRAG_WAIT);
 325
 326        /* On Maui and Spirit use the global seqnum on DCU */
 327        if (ah->ah_mac_version < AR5K_SREV_AR5211)
 328                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 329                                        AR5K_DCU_MISC_SEQNUM_CTL);
 330
 331        /* Constant bit rate period */
 332        if (tq->tqi_cbr_period) {
 333                ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
 334                                        AR5K_QCU_CBRCFG_INTVAL) |
 335                                        AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
 336                                        AR5K_QCU_CBRCFG_ORN_THRES),
 337                                        AR5K_QUEUE_CBRCFG(queue));
 338
 339                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 340                                        AR5K_QCU_MISC_FRSHED_CBR);
 341
 342                if (tq->tqi_cbr_overflow_limit)
 343                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 344                                        AR5K_QCU_MISC_CBR_THRES_ENABLE);
 345        }
 346
 347        /* Ready time interval */
 348        if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
 349                ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
 350                                        AR5K_QCU_RDYTIMECFG_INTVAL) |
 351                                        AR5K_QCU_RDYTIMECFG_ENABLE,
 352                                        AR5K_QUEUE_RDYTIMECFG(queue));
 353
 354        if (tq->tqi_burst_time) {
 355                ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
 356                                        AR5K_DCU_CHAN_TIME_DUR) |
 357                                        AR5K_DCU_CHAN_TIME_ENABLE,
 358                                        AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
 359
 360                if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
 361                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 362                                        AR5K_QCU_MISC_RDY_VEOL_POLICY);
 363        }
 364
 365        /* Enable/disable Post frame backoff */
 366        if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
 367                ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
 368                                        AR5K_QUEUE_DFS_MISC(queue));
 369
 370        /* Enable/disable fragmentation burst backoff */
 371        if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
 372                ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
 373                                        AR5K_QUEUE_DFS_MISC(queue));
 374
 375        /*
 376         * Set registers by queue type
 377         */
 378        switch (tq->tqi_type) {
 379        case AR5K_TX_QUEUE_BEACON:
 380                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 381                                AR5K_QCU_MISC_FRSHED_DBA_GT |
 382                                AR5K_QCU_MISC_CBREXP_BCN_DIS |
 383                                AR5K_QCU_MISC_BCN_ENABLE);
 384
 385                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 386                                (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
 387                                AR5K_DCU_MISC_ARBLOCK_CTL_S) |
 388                                AR5K_DCU_MISC_ARBLOCK_IGNORE |
 389                                AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
 390                                AR5K_DCU_MISC_BCN_ENABLE);
 391                break;
 392
 393        case AR5K_TX_QUEUE_CAB:
 394                /* XXX: use BCN_SENT_GT, if we can figure out how */
 395                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 396                                        AR5K_QCU_MISC_FRSHED_DBA_GT |
 397                                        AR5K_QCU_MISC_CBREXP_DIS |
 398                                        AR5K_QCU_MISC_CBREXP_BCN_DIS);
 399
 400                ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
 401                                        (AR5K_TUNE_SW_BEACON_RESP -
 402                                        AR5K_TUNE_DMA_BEACON_RESP) -
 403                                AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
 404                                        AR5K_QCU_RDYTIMECFG_ENABLE,
 405                                        AR5K_QUEUE_RDYTIMECFG(queue));
 406
 407                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 408                                        (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
 409                                        AR5K_DCU_MISC_ARBLOCK_CTL_S));
 410                break;
 411
 412        case AR5K_TX_QUEUE_UAPSD:
 413                AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 414                                        AR5K_QCU_MISC_CBREXP_DIS);
 415                break;
 416
 417        case AR5K_TX_QUEUE_DATA:
 418        default:
 419                        break;
 420        }
 421
 422        /* TODO: Handle frame compression */
 423
 424        /*
 425         * Enable interrupts for this tx queue
 426         * in the secondary interrupt mask registers
 427         */
 428        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
 429                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
 430
 431        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
 432                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
 433
 434        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
 435                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
 436
 437        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
 438                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
 439
 440        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
 441                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
 442
 443        if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
 444                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
 445
 446        if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
 447                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
 448
 449        if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
 450                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
 451
 452        if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
 453                AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
 454
 455        /* Update secondary interrupt mask registers */
 456
 457        /* Filter out inactive queues */
 458        ah->ah_txq_imr_txok &= ah->ah_txq_status;
 459        ah->ah_txq_imr_txerr &= ah->ah_txq_status;
 460        ah->ah_txq_imr_txurn &= ah->ah_txq_status;
 461        ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
 462        ah->ah_txq_imr_txeol &= ah->ah_txq_status;
 463        ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
 464        ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
 465        ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
 466        ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
 467
 468        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
 469                                        AR5K_SIMR0_QCU_TXOK) |
 470                                        AR5K_REG_SM(ah->ah_txq_imr_txdesc,
 471                                        AR5K_SIMR0_QCU_TXDESC),
 472                                        AR5K_SIMR0);
 473
 474        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
 475                                        AR5K_SIMR1_QCU_TXERR) |
 476                                        AR5K_REG_SM(ah->ah_txq_imr_txeol,
 477                                        AR5K_SIMR1_QCU_TXEOL),
 478                                        AR5K_SIMR1);
 479
 480        /* Update SIMR2 but don't overwrite rest simr2 settings */
 481        AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
 482        AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
 483                                AR5K_REG_SM(ah->ah_txq_imr_txurn,
 484                                AR5K_SIMR2_QCU_TXURN));
 485
 486        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
 487                                AR5K_SIMR3_QCBRORN) |
 488                                AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
 489                                AR5K_SIMR3_QCBRURN),
 490                                AR5K_SIMR3);
 491
 492        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
 493                                AR5K_SIMR4_QTRIG), AR5K_SIMR4);
 494
 495        /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
 496        ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
 497                                AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
 498
 499        /* No queue has TXNOFRM enabled, disable the interrupt
 500         * by setting AR5K_TXNOFRM to zero */
 501        if (ah->ah_txq_imr_nofrm == 0)
 502                ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
 503
 504        /* Set QCU mask for this DCU to save power */
 505        AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
 506
 507        return 0;
 508}
 509
 510
 511/**************************\
 512* Global QCU/DCU functions *
 513\**************************/
 514
 515/**
 516 * ath5k_hw_set_ifs_intervals  - Set global inter-frame spaces on DCU
 517 *
 518 * @ah The &struct ath5k_hw
 519 * @slot_time Slot time in us
 520 *
 521 * Sets the global IFS intervals on DCU (also works on AR5210) for
 522 * the given slot time and the current bwmode.
 523 */
 524int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
 525{
 526        struct ieee80211_channel *channel = ah->ah_current_channel;
 527        struct ath5k_softc *sc = ah->ah_sc;
 528        struct ieee80211_rate *rate;
 529        u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
 530        u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
 531
 532        if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
 533                return -EINVAL;
 534
 535        sifs = ath5k_hw_get_default_sifs(ah);
 536        sifs_clock = ath5k_hw_htoclock(ah, sifs);
 537
 538        /* EIFS
 539         * Txtime of ack at lowest rate + SIFS + DIFS
 540         * (DIFS = SIFS + 2 * Slot time)
 541         *
 542         * Note: HAL has some predefined values for EIFS
 543         * Turbo:   (37 + 2 * 6)
 544         * Default: (74 + 2 * 9)
 545         * Half:    (149 + 2 * 13)
 546         * Quarter: (298 + 2 * 21)
 547         *
 548         * (74 + 2 * 6) for AR5210 default and turbo !
 549         *
 550         * According to the formula we have
 551         * ack_tx_time = 25 for turbo and
 552         * ack_tx_time = 42.5 * clock multiplier
 553         * for default/half/quarter.
 554         *
 555         * This can't be right, 42 is what we would get
 556         * from ath5k_hw_get_frame_dur_for_bwmode or
 557         * ieee80211_generic_frame_duration for zero frame
 558         * length and without SIFS !
 559         *
 560         * Also we have different lowest rate for 802.11a
 561         */
 562        if (channel->hw_value & CHANNEL_5GHZ)
 563                rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
 564        else
 565                rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
 566
 567        ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
 568
 569        /* ack_tx_time includes an SIFS already */
 570        eifs = ack_tx_time + sifs + 2 * slot_time;
 571        eifs_clock = ath5k_hw_htoclock(ah, eifs);
 572
 573        /* Set IFS settings on AR5210 */
 574        if (ah->ah_version == AR5K_AR5210) {
 575                u32 pifs, pifs_clock, difs, difs_clock;
 576
 577                /* Set slot time */
 578                ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
 579
 580                /* Set EIFS */
 581                eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
 582
 583                /* PIFS = Slot time + SIFS */
 584                pifs = slot_time + sifs;
 585                pifs_clock = ath5k_hw_htoclock(ah, pifs);
 586                pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
 587
 588                /* DIFS = SIFS + 2 * Slot time */
 589                difs = sifs + 2 * slot_time;
 590                difs_clock = ath5k_hw_htoclock(ah, difs);
 591
 592                /* Set SIFS/DIFS */
 593                ath5k_hw_reg_write(ah, (difs_clock <<
 594                                AR5K_IFS0_DIFS_S) | sifs_clock,
 595                                AR5K_IFS0);
 596
 597                /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
 598                ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
 599                                (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
 600                                AR5K_IFS1);
 601
 602                return 0;
 603        }
 604
 605        /* Set IFS slot time */
 606        ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
 607
 608        /* Set EIFS interval */
 609        ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
 610
 611        /* Set SIFS interval in usecs */
 612        AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
 613                                AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
 614                                sifs);
 615
 616        /* Set SIFS interval in clock cycles */
 617        ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
 618
 619        return 0;
 620}
 621
 622
 623int ath5k_hw_init_queues(struct ath5k_hw *ah)
 624{
 625        int i, ret;
 626
 627        /* TODO: HW Compression support for data queues */
 628        /* TODO: Burst prefetch for data queues */
 629
 630        /*
 631         * Reset queues and start beacon timers at the end of the reset routine
 632         * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
 633         * Note: If we want we can assign multiple qcus on one dcu.
 634         */
 635        if (ah->ah_version != AR5K_AR5210)
 636                for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
 637                        ret = ath5k_hw_reset_tx_queue(ah, i);
 638                        if (ret) {
 639                                ATH5K_ERR(ah->ah_sc,
 640                                        "failed to reset TX queue #%d\n", i);
 641                                return ret;
 642                        }
 643                }
 644        else
 645                /* No QCU/DCU on AR5210, just set tx
 646                 * retry limits. We set IFS parameters
 647                 * on ath5k_hw_set_ifs_intervals */
 648                ath5k_hw_set_tx_retry_limits(ah, 0);
 649
 650        /* Set the turbo flag when operating on 40MHz */
 651        if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
 652                AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
 653                                AR5K_DCU_GBL_IFS_MISC_TURBO_MODE);
 654
 655        /* If we didn't set IFS timings through
 656         * ath5k_hw_set_coverage_class make sure
 657         * we set them here */
 658        if (!ah->ah_coverage_class) {
 659                unsigned int slot_time = ath5k_hw_get_default_slottime(ah);
 660                ath5k_hw_set_ifs_intervals(ah, slot_time);
 661        }
 662
 663        return 0;
 664}
 665