The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2006 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 #include "ah_desc.h"
   26 
   27 #include "ar5211/ar5211.h"
   28 #include "ar5211/ar5211reg.h"
   29 #include "ar5211/ar5211desc.h"
   30 
   31 /*
   32  * Update Tx FIFO trigger level.
   33  *
   34  * Set bIncTrigLevel to TRUE to increase the trigger level.
   35  * Set bIncTrigLevel to FALSE to decrease the trigger level.
   36  *
   37  * Returns TRUE if the trigger level was updated
   38  */
   39 HAL_BOOL
   40 ar5211UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel)
   41 {
   42         uint32_t curTrigLevel, txcfg;
   43         HAL_INT ints = ar5211GetInterrupts(ah);
   44 
   45         /*
   46          * Disable chip interrupts. This is because halUpdateTxTrigLevel
   47          * is called from both ISR and non-ISR contexts.
   48          */
   49         ar5211SetInterrupts(ah, ints &~ HAL_INT_GLOBAL);
   50         txcfg = OS_REG_READ(ah, AR_TXCFG);
   51         curTrigLevel = (txcfg & AR_TXCFG_FTRIG_M) >> AR_TXCFG_FTRIG_S;
   52         if (bIncTrigLevel){
   53                 /* increase the trigger level */
   54                 curTrigLevel = curTrigLevel +
   55                         ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2);
   56         } else {
   57                 /* decrease the trigger level if not already at the minimum */
   58                 if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) {
   59                         /* decrease the trigger level */
   60                         curTrigLevel--;
   61                 } else {
   62                         /* no update to the trigger level */
   63                         /* re-enable chip interrupts */
   64                         ar5211SetInterrupts(ah, ints);
   65                         return AH_FALSE;
   66                 }
   67         }
   68         /* Update the trigger level */
   69         OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_TXCFG_FTRIG_M) |
   70                 ((curTrigLevel << AR_TXCFG_FTRIG_S) & AR_TXCFG_FTRIG_M));
   71         /* re-enable chip interrupts */
   72         ar5211SetInterrupts(ah, ints);
   73         return AH_TRUE;
   74 }
   75 
   76 /*
   77  * Set the properties of the tx queue with the parameters
   78  * from qInfo.  The queue must previously have been setup
   79  * with a call to ar5211SetupTxQueue.
   80  */
   81 HAL_BOOL
   82 ar5211SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo)
   83 {
   84         struct ath_hal_5211 *ahp = AH5211(ah);
   85 
   86         if (q >= HAL_NUM_TX_QUEUES) {
   87                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
   88                     __func__, q);
   89                 return AH_FALSE;
   90         }
   91         return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo);
   92 }
   93 
   94 /*
   95  * Return the properties for the specified tx queue.
   96  */
   97 HAL_BOOL
   98 ar5211GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo)
   99 {
  100         struct ath_hal_5211 *ahp = AH5211(ah);
  101 
  102         if (q >= HAL_NUM_TX_QUEUES) {
  103                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
  104                     __func__, q);
  105                 return AH_FALSE;
  106         }
  107         return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]);
  108 }
  109 
  110 /*
  111  * Allocate and initialize a tx DCU/QCU combination.
  112  */
  113 int
  114 ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
  115         const HAL_TXQ_INFO *qInfo)
  116 {
  117         struct ath_hal_5211 *ahp = AH5211(ah);
  118         HAL_TX_QUEUE_INFO *qi;
  119         int q;
  120 
  121         switch (type) {
  122         case HAL_TX_QUEUE_BEACON:
  123                 q = 9;
  124                 break;
  125         case HAL_TX_QUEUE_CAB:
  126                 q = 8;
  127                 break;
  128         case HAL_TX_QUEUE_DATA:
  129                 q = 0;
  130                 if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE)
  131                         return q;
  132                 break;
  133         default:
  134                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n",
  135                     __func__, type);
  136                 return -1;
  137         }
  138 
  139         HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
  140 
  141         qi = &ahp->ah_txq[q];
  142         if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) {
  143                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n",
  144                     __func__, q);
  145                 return -1;
  146         }
  147         OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO));
  148         qi->tqi_type = type;
  149         if (qInfo == AH_NULL) {
  150                 /* by default enable OK+ERR+DESC+URN interrupts */
  151                 qi->tqi_qflags =
  152                           HAL_TXQ_TXOKINT_ENABLE
  153                         | HAL_TXQ_TXERRINT_ENABLE
  154                         | HAL_TXQ_TXDESCINT_ENABLE
  155                         | HAL_TXQ_TXURNINT_ENABLE
  156                         ;
  157                 qi->tqi_aifs = INIT_AIFS;
  158                 qi->tqi_cwmin = HAL_TXQ_USEDEFAULT;     /* NB: do at reset */
  159                 qi->tqi_cwmax = INIT_CWMAX;
  160                 qi->tqi_shretry = INIT_SH_RETRY;
  161                 qi->tqi_lgretry = INIT_LG_RETRY;
  162         } else
  163                 (void) ar5211SetTxQueueProps(ah, q, qInfo);
  164         return q;
  165 }
  166 
  167 /*
  168  * Update the h/w interrupt registers to reflect a tx q's configuration.
  169  */
  170 static void
  171 setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi)
  172 {
  173         struct ath_hal_5211 *ahp = AH5211(ah);
  174 
  175         HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
  176             "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__
  177                 , ahp->ah_txOkInterruptMask
  178                 , ahp->ah_txErrInterruptMask
  179                 , ahp->ah_txDescInterruptMask
  180                 , ahp->ah_txEolInterruptMask
  181                 , ahp->ah_txUrnInterruptMask
  182         );
  183 
  184         OS_REG_WRITE(ah, AR_IMR_S0,
  185                   SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
  186                 | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC)
  187         );
  188         OS_REG_WRITE(ah, AR_IMR_S1,
  189                   SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
  190                 | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL)
  191         );
  192         OS_REG_RMW_FIELD(ah, AR_IMR_S2,
  193                 AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
  194 }
  195 
  196 /*
  197  * Free a tx DCU/QCU combination.
  198  */
  199 HAL_BOOL
  200 ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q)
  201 {
  202         struct ath_hal_5211 *ahp = AH5211(ah);
  203         HAL_TX_QUEUE_INFO *qi;
  204 
  205         if (q >= HAL_NUM_TX_QUEUES) {
  206                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
  207                     __func__, q);
  208                 return AH_FALSE;
  209         }
  210         qi = &ahp->ah_txq[q];
  211         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
  212                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
  213                     __func__, q);
  214                 return AH_FALSE;
  215         }
  216 
  217         HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q);
  218 
  219         qi->tqi_type = HAL_TX_QUEUE_INACTIVE;
  220         ahp->ah_txOkInterruptMask &= ~(1 << q);
  221         ahp->ah_txErrInterruptMask &= ~(1 << q);
  222         ahp->ah_txDescInterruptMask &= ~(1 << q);
  223         ahp->ah_txEolInterruptMask &= ~(1 << q);
  224         ahp->ah_txUrnInterruptMask &= ~(1 << q);
  225         setTxQInterrupts(ah, qi);
  226 
  227         return AH_TRUE;
  228 }
  229 
  230 /*
  231  * Set the retry, aifs, cwmin/max, readyTime regs for specified queue
  232  */
  233 HAL_BOOL
  234 ar5211ResetTxQueue(struct ath_hal *ah, u_int q)
  235 {
  236         struct ath_hal_5211 *ahp = AH5211(ah);
  237         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
  238         HAL_TX_QUEUE_INFO *qi;
  239         uint32_t cwMin, chanCwMin, value;
  240 
  241         if (q >= HAL_NUM_TX_QUEUES) {
  242                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
  243                     __func__, q);
  244                 return AH_FALSE;
  245         }
  246         qi = &ahp->ah_txq[q];
  247         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
  248                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
  249                     __func__, q);
  250                 return AH_TRUE;         /* XXX??? */
  251         }
  252 
  253         if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) {
  254                 /*
  255                  * Select cwmin according to channel type.
  256                  * NB: chan can be NULL during attach
  257                  */
  258                 if (chan && IEEE80211_IS_CHAN_B(chan))
  259                         chanCwMin = INIT_CWMIN_11B;
  260                 else
  261                         chanCwMin = INIT_CWMIN;
  262                 /* make sure that the CWmin is of the form (2^n - 1) */
  263                 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1)
  264                         ;
  265         } else
  266                 cwMin = qi->tqi_cwmin;
  267 
  268         /* set cwMin/Max and AIFS values */
  269         OS_REG_WRITE(ah, AR_DLCL_IFS(q),
  270                   SM(cwMin, AR_D_LCL_IFS_CWMIN)
  271                 | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
  272                 | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
  273 
  274         /* Set retry limit values */
  275         OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), 
  276                    SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
  277                  | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
  278                  | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG)
  279                  | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
  280         );
  281 
  282         /* enable early termination on the QCU */
  283         OS_REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
  284 
  285         if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
  286                 /* Configure DCU to use the global sequence count */
  287                 OS_REG_WRITE(ah, AR_DMISC(q), AR5311_D_MISC_SEQ_NUM_CONTROL);
  288         }
  289         /* multiqueue support */
  290         if (qi->tqi_cbrPeriod) {
  291                 OS_REG_WRITE(ah, AR_QCBRCFG(q), 
  292                           SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL)
  293                         | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH));
  294                 OS_REG_WRITE(ah, AR_QMISC(q),
  295                         OS_REG_READ(ah, AR_QMISC(q)) |
  296                         AR_Q_MISC_FSP_CBR |
  297                         (qi->tqi_cbrOverflowLimit ?
  298                                 AR_Q_MISC_CBR_EXP_CNTR_LIMIT : 0));
  299         }
  300         if (qi->tqi_readyTime) {
  301                 OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
  302                         SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | 
  303                         AR_Q_RDYTIMECFG_EN);
  304         }
  305         if (qi->tqi_burstTime) {
  306                 OS_REG_WRITE(ah, AR_DCHNTIME(q),
  307                         SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
  308                         AR_D_CHNTIME_EN);
  309                 if (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE) {
  310                         OS_REG_WRITE(ah, AR_QMISC(q),
  311                              OS_REG_READ(ah, AR_QMISC(q)) |
  312                              AR_Q_MISC_RDYTIME_EXP_POLICY);
  313                 }
  314         }
  315 
  316         if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) {
  317                 OS_REG_WRITE(ah, AR_DMISC(q),
  318                         OS_REG_READ(ah, AR_DMISC(q)) |
  319                         AR_D_MISC_POST_FR_BKOFF_DIS);
  320         }
  321         if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) {
  322                 OS_REG_WRITE(ah, AR_DMISC(q),
  323                         OS_REG_READ(ah, AR_DMISC(q)) |
  324                         AR_D_MISC_FRAG_BKOFF_EN);
  325         }
  326         switch (qi->tqi_type) {
  327         case HAL_TX_QUEUE_BEACON:
  328                 /* Configure QCU for beacons */
  329                 OS_REG_WRITE(ah, AR_QMISC(q),
  330                         OS_REG_READ(ah, AR_QMISC(q))
  331                         | AR_Q_MISC_FSP_DBA_GATED
  332                         | AR_Q_MISC_BEACON_USE
  333                         | AR_Q_MISC_CBR_INCR_DIS1);
  334                 /* Configure DCU for beacons */
  335                 value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
  336                         | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS;
  337                 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU)
  338                         value |= AR5311_D_MISC_SEQ_NUM_CONTROL;
  339                 OS_REG_WRITE(ah, AR_DMISC(q), value);
  340                 break;
  341         case HAL_TX_QUEUE_CAB:
  342                 /* Configure QCU for CAB (Crap After Beacon) frames */
  343                 OS_REG_WRITE(ah, AR_QMISC(q),
  344                         OS_REG_READ(ah, AR_QMISC(q))
  345                         | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1
  346                         | AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY);
  347 
  348                 value = (ahp->ah_beaconInterval
  349                         - (ah->ah_config.ah_sw_beacon_response_time
  350                                 - ah->ah_config.ah_dma_beacon_response_time)
  351                         - ah->ah_config.ah_additional_swba_backoff) * 1024;
  352                 OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN);
  353 
  354                 /* Configure DCU for CAB */
  355                 value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S);
  356                 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU)
  357                         value |= AR5311_D_MISC_SEQ_NUM_CONTROL;
  358                 OS_REG_WRITE(ah, AR_QMISC(q), value);
  359                 break;
  360         default:
  361                 /* NB: silence compiler */
  362                 break;
  363         }
  364 
  365         /*
  366          * Always update the secondary interrupt mask registers - this
  367          * could be a new queue getting enabled in a running system or
  368          * hw getting re-initialized during a reset!
  369          *
  370          * Since we don't differentiate between tx interrupts corresponding
  371          * to individual queues - secondary tx mask regs are always unmasked;
  372          * tx interrupts are enabled/disabled for all queues collectively
  373          * using the primary mask reg
  374          */
  375         if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE)
  376                 ahp->ah_txOkInterruptMask |= 1 << q;
  377         else
  378                 ahp->ah_txOkInterruptMask &= ~(1 << q);
  379         if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE)
  380                 ahp->ah_txErrInterruptMask |= 1 << q;
  381         else
  382                 ahp->ah_txErrInterruptMask &= ~(1 << q);
  383         if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE)
  384                 ahp->ah_txDescInterruptMask |= 1 << q;
  385         else
  386                 ahp->ah_txDescInterruptMask &= ~(1 << q);
  387         if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE)
  388                 ahp->ah_txEolInterruptMask |= 1 << q;
  389         else
  390                 ahp->ah_txEolInterruptMask &= ~(1 << q);
  391         if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE)
  392                 ahp->ah_txUrnInterruptMask |= 1 << q;
  393         else
  394                 ahp->ah_txUrnInterruptMask &= ~(1 << q);
  395         setTxQInterrupts(ah, qi);
  396 
  397         return AH_TRUE;
  398 }
  399 
  400 /*
  401  * Get the TXDP for the specified data queue.
  402  */
  403 uint32_t
  404 ar5211GetTxDP(struct ath_hal *ah, u_int q)
  405 {
  406         HALASSERT(q < HAL_NUM_TX_QUEUES);
  407         return OS_REG_READ(ah, AR_QTXDP(q));
  408 }
  409 
  410 /*
  411  * Set the TxDP for the specified tx queue.
  412  */
  413 HAL_BOOL
  414 ar5211SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp)
  415 {
  416         HALASSERT(q < HAL_NUM_TX_QUEUES);
  417         HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
  418 
  419         /*
  420          * Make sure that TXE is deasserted before setting the TXDP.  If TXE
  421          * is still asserted, setting TXDP will have no effect.
  422          */
  423         HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0);
  424 
  425         OS_REG_WRITE(ah, AR_QTXDP(q), txdp);
  426 
  427         return AH_TRUE;
  428 }
  429 
  430 /*
  431  * Set Transmit Enable bits for the specified queues.
  432  */
  433 HAL_BOOL
  434 ar5211StartTxDma(struct ath_hal *ah, u_int q)
  435 {
  436         HALASSERT(q < HAL_NUM_TX_QUEUES);
  437         HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
  438 
  439         /* Check that queue is not already active */
  440         HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1<<q)) == 0);
  441 
  442         HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
  443 
  444         /* Check to be sure we're not enabling a q that has its TXD bit set. */
  445         HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0);
  446 
  447         OS_REG_WRITE(ah, AR_Q_TXE, 1 << q);
  448         return AH_TRUE;
  449 }
  450 
  451 /*
  452  * Return the number of frames pending on the specified queue.
  453  */
  454 uint32_t
  455 ar5211NumTxPending(struct ath_hal *ah, u_int q)
  456 {
  457         uint32_t n;
  458 
  459         HALASSERT(q < HAL_NUM_TX_QUEUES);
  460         HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
  461 
  462         n = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT_M;
  463         /*
  464          * Pending frame count (PFC) can momentarily go to zero
  465          * while TXE remains asserted.  In other words a PFC of
  466          * zero is not sufficient to say that the queue has stopped.
  467          */
  468         if (n == 0 && (OS_REG_READ(ah, AR_Q_TXE) & (1<<q)))
  469                 n = 1;                  /* arbitrarily pick 1 */
  470         return n;
  471 }
  472 
  473 /*
  474  * Stop transmit on the specified queue
  475  */
  476 HAL_BOOL
  477 ar5211StopTxDma(struct ath_hal *ah, u_int q)
  478 {
  479         int i;
  480 
  481         HALASSERT(q < HAL_NUM_TX_QUEUES);
  482         HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
  483 
  484         OS_REG_WRITE(ah, AR_Q_TXD, 1<<q);
  485         for (i = 0; i < 10000; i++) {
  486                 if (ar5211NumTxPending(ah, q) == 0)
  487                         break;
  488                 OS_DELAY(10);
  489         }
  490         OS_REG_WRITE(ah, AR_Q_TXD, 0);
  491 
  492         return (i < 10000);
  493 }
  494 
  495 /*
  496  * Descriptor Access Functions
  497  */
  498 
  499 #define VALID_PKT_TYPES \
  500         ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
  501          (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
  502          (1<<HAL_PKT_TYPE_BEACON))
  503 #define isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
  504 #define VALID_TX_RATES \
  505         ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
  506          (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
  507          (1<<0x1d)|(1<<0x18)|(1<<0x1c))
  508 #define isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
  509 
  510 HAL_BOOL
  511 ar5211SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
  512         u_int pktLen,
  513         u_int hdrLen,
  514         HAL_PKT_TYPE type,
  515         u_int txPower,
  516         u_int txRate0, u_int txTries0,
  517         u_int keyIx,
  518         u_int antMode,
  519         u_int flags,
  520         u_int rtsctsRate,
  521         u_int rtsctsDuration,
  522         u_int compicvLen, 
  523         u_int compivLen,
  524         u_int comp)
  525 {
  526         struct ar5211_desc *ads = AR5211DESC(ds);
  527 
  528         (void) hdrLen;
  529         (void) txPower;
  530         (void) rtsctsRate; (void) rtsctsDuration;
  531 
  532         HALASSERT(txTries0 != 0);
  533         HALASSERT(isValidPktType(type));
  534         HALASSERT(isValidTxRate(txRate0));
  535         /* XXX validate antMode */
  536 
  537         ads->ds_ctl0 = (pktLen & AR_FrameLen)
  538                      | (txRate0 << AR_XmitRate_S)
  539                      | (antMode << AR_AntModeXmit_S)
  540                      | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0)
  541                      | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0)
  542                      | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0)
  543                      | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
  544                      ;
  545         ads->ds_ctl1 = (type << 26)
  546                      | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
  547                      ;
  548 
  549         if (keyIx != HAL_TXKEYIX_INVALID) {
  550                 ads->ds_ctl1 |=
  551                         (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx;
  552                 ads->ds_ctl0 |= AR_EncryptKeyValid;
  553         }
  554         return AH_TRUE;
  555 #undef RATE
  556 }
  557 
  558 HAL_BOOL
  559 ar5211SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
  560         u_int txRate1, u_int txTries1,
  561         u_int txRate2, u_int txTries2,
  562         u_int txRate3, u_int txTries3)
  563 {
  564         (void) ah; (void) ds;
  565         (void) txRate1; (void) txTries1;
  566         (void) txRate2; (void) txTries2;
  567         (void) txRate3; (void) txTries3;
  568         return AH_FALSE;
  569 }
  570 
  571 void
  572 ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds)
  573 {
  574         struct ar5211_desc *ads = AR5211DESC(ds);
  575 
  576         ads->ds_ctl0 |= AR_TxInterReq;
  577 }
  578 
  579 HAL_BOOL
  580 ar5211FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
  581         HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int qcuId,
  582         u_int descId, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
  583         const struct ath_desc *ds0)
  584 {
  585         struct ar5211_desc *ads = AR5211DESC(ds);
  586         uint32_t segLen = segLenList[0];
  587 
  588         ds->ds_data = bufAddrList[0];
  589 
  590         HALASSERT((segLen &~ AR_BufLen) == 0);
  591 
  592         if (firstSeg) {
  593                 /*
  594                  * First descriptor, don't clobber xmit control data
  595                  * setup by ar5211SetupTxDesc.
  596                  */
  597                 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More);
  598         } else if (lastSeg) {           /* !firstSeg && lastSeg */
  599                 /*
  600                  * Last descriptor in a multi-descriptor frame,
  601                  * copy the transmit parameters from the first
  602                  * frame for processing on completion. 
  603                  */
  604                 ads->ds_ctl0 = AR5211DESC_CONST(ds0)->ds_ctl0;
  605                 ads->ds_ctl1 = segLen;
  606         } else {                        /* !firstSeg && !lastSeg */
  607                 /*
  608                  * Intermediate descriptor in a multi-descriptor frame.
  609                  */
  610                 ads->ds_ctl0 = 0;
  611                 ads->ds_ctl1 = segLen | AR_More;
  612         }
  613         ads->ds_status0 = ads->ds_status1 = 0;
  614         return AH_TRUE;
  615 }
  616 
  617 /*
  618  * Processing of HW TX descriptor.
  619  */
  620 HAL_STATUS
  621 ar5211ProcTxDesc(struct ath_hal *ah,
  622         struct ath_desc *ds, struct ath_tx_status *ts)
  623 {
  624         struct ar5211_desc *ads = AR5211DESC(ds);
  625 
  626         if ((ads->ds_status1 & AR_Done) == 0)
  627                 return HAL_EINPROGRESS;
  628 
  629         /* Update software copies of the HW status */
  630         ts->ts_seqnum = MS(ads->ds_status1, AR_SeqNum);
  631         ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp);
  632         ts->ts_status = 0;
  633         if ((ads->ds_status0 & AR_FrmXmitOK) == 0) {
  634                 if (ads->ds_status0 & AR_ExcessiveRetries)
  635                         ts->ts_status |= HAL_TXERR_XRETRY;
  636                 if (ads->ds_status0 & AR_Filtered)
  637                         ts->ts_status |= HAL_TXERR_FILT;
  638                 if (ads->ds_status0 & AR_FIFOUnderrun)
  639                         ts->ts_status |= HAL_TXERR_FIFO;
  640         }
  641         ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate);
  642         ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength);
  643         ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt);
  644         ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt);
  645         ts->ts_virtcol = MS(ads->ds_status0, AR_VirtCollCnt);
  646         ts->ts_antenna = 0;             /* NB: don't know */
  647         ts->ts_finaltsi = 0;
  648         /*
  649          * NB: the number of retries is one less than it should be.
  650          * Also, 0 retries and 1 retry are both reported as 0 retries.
  651          */
  652         if (ts->ts_shortretry > 0)
  653                 ts->ts_shortretry++;
  654         if (ts->ts_longretry > 0)
  655                 ts->ts_longretry++;
  656 
  657         return HAL_OK;
  658 }
  659 
  660 /*
  661  * Determine which tx queues need interrupt servicing.
  662  * STUB.
  663  */
  664 void
  665 ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs)
  666 {
  667         return;
  668 }
  669 
  670 /*
  671  * Retrieve the rate table from the given TX completion descriptor
  672  */
  673 HAL_BOOL
  674 ar5211GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries)
  675 {
  676         return AH_FALSE;
  677 }
  678 
  679 void
  680 ar5211SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link)
  681 {
  682         struct ar5211_desc *ads = AR5211DESC(ds);
  683 
  684         ads->ds_link = link;
  685 }
  686 
  687 void
  688 ar5211GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link)
  689 {
  690         struct ar5211_desc *ads = AR5211DESC(ds);
  691 
  692         *link = ads->ds_link;
  693 }
  694 
  695 void
  696 ar5211GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr)
  697 {
  698         struct ar5211_desc *ads = AR5211DESC(ds);
  699 
  700         *linkptr = &ads->ds_link;
  701 }

Cache object: 33f469d29810833e77b743b251c736fe


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.