1250003Sadrian/*
2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc.
3250003Sadrian *
4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5250003Sadrian * purpose with or without fee is hereby granted, provided that the above
6250003Sadrian * copyright notice and this permission notice appear in all copies.
7250003Sadrian *
8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14250003Sadrian * PERFORMANCE OF THIS SOFTWARE.
15250003Sadrian */
16250003Sadrian
17250003Sadrian#include "opt_ah.h"
18250003Sadrian
19250003Sadrian#include "ah.h"
20250003Sadrian#include "ah_desc.h"
21250003Sadrian#include "ah_internal.h"
22250003Sadrian
23250003Sadrian#include "ar9300/ar9300.h"
24250003Sadrian#include "ar9300/ar9300reg.h"
25250003Sadrian#include "ar9300/ar9300phy.h"
26250003Sadrian#include "ar9300/ar9300desc.h"
27250003Sadrian
28250008Sadrian#define TU_TO_USEC(_tu)         ((_tu) << 10)
29250008Sadrian#define ONE_EIGHTH_TU_TO_USEC(_tu8)     ((_tu8) << 7)
30250008Sadrian
31250003Sadrian/*
32250003Sadrian * Update Tx FIFO trigger level.
33250003Sadrian *
34250003Sadrian * Set b_inc_trig_level to TRUE to increase the trigger level.
35250003Sadrian * Set b_inc_trig_level to FALSE to decrease the trigger level.
36250003Sadrian *
37250003Sadrian * Returns TRUE if the trigger level was updated
38250003Sadrian */
39250003SadrianHAL_BOOL
40250003Sadrianar9300_update_tx_trig_level(struct ath_hal *ah, HAL_BOOL b_inc_trig_level)
41250003Sadrian{
42250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
43250003Sadrian    u_int32_t txcfg, cur_level, new_level;
44250003Sadrian    HAL_INT omask;
45250003Sadrian
46250008Sadrian    if (AH9300(ah)->ah_tx_trig_level >= MAX_TX_FIFO_THRESHOLD &&
47250003Sadrian        b_inc_trig_level)
48250003Sadrian    {
49250003Sadrian        return AH_FALSE;
50250003Sadrian    }
51250003Sadrian
52250003Sadrian    /*
53250003Sadrian     * Disable interrupts while futzing with the fifo level.
54250003Sadrian     */
55250003Sadrian    omask = ar9300_set_interrupts(ah, ahp->ah_mask_reg &~ HAL_INT_GLOBAL, 0);
56250003Sadrian
57250003Sadrian    txcfg = OS_REG_READ(ah, AR_TXCFG);
58250003Sadrian    cur_level = MS(txcfg, AR_FTRIG);
59250003Sadrian    new_level = cur_level;
60250003Sadrian
61250003Sadrian    if (b_inc_trig_level)  {   /* increase the trigger level */
62250003Sadrian        if (cur_level < MAX_TX_FIFO_THRESHOLD) {
63250003Sadrian            new_level++;
64250003Sadrian        }
65250003Sadrian    } else if (cur_level > MIN_TX_FIFO_THRESHOLD) {
66250003Sadrian        new_level--;
67250003Sadrian    }
68250003Sadrian
69250003Sadrian    if (new_level != cur_level) {
70250003Sadrian        /* Update the trigger level */
71250003Sadrian        OS_REG_WRITE(ah,
72250003Sadrian            AR_TXCFG, (txcfg &~ AR_FTRIG) | SM(new_level, AR_FTRIG));
73250003Sadrian    }
74250003Sadrian
75250003Sadrian    /* re-enable chip interrupts */
76250003Sadrian    ar9300_set_interrupts(ah, omask, 0);
77250003Sadrian
78250008Sadrian    AH9300(ah)->ah_tx_trig_level = new_level;
79250003Sadrian
80250003Sadrian    return (new_level != cur_level);
81250003Sadrian}
82250003Sadrian
83250003Sadrian/*
84250003Sadrian * Returns the value of Tx Trigger Level
85250003Sadrian */
86250003Sadrianu_int16_t
87250003Sadrianar9300_get_tx_trig_level(struct ath_hal *ah)
88250003Sadrian{
89250008Sadrian    return (AH9300(ah)->ah_tx_trig_level);
90250003Sadrian}
91250003Sadrian
92250003Sadrian/*
93250003Sadrian * Set the properties of the tx queue with the parameters
94250003Sadrian * from q_info.
95250003Sadrian */
96250003SadrianHAL_BOOL
97250003Sadrianar9300_set_tx_queue_props(struct ath_hal *ah, int q, const HAL_TXQ_INFO *q_info)
98250003Sadrian{
99250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
100250003Sadrian    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
101250003Sadrian
102250008Sadrian    if (q >= p_cap->halTotalQueues) {
103250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q);
104250003Sadrian        return AH_FALSE;
105250003Sadrian    }
106250008Sadrian    return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], q_info);
107250003Sadrian}
108250003Sadrian
109250003Sadrian/*
110250003Sadrian * Return the properties for the specified tx queue.
111250003Sadrian */
112250003SadrianHAL_BOOL
113250003Sadrianar9300_get_tx_queue_props(struct ath_hal *ah, int q, HAL_TXQ_INFO *q_info)
114250003Sadrian{
115250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
116250003Sadrian    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
117250003Sadrian
118250003Sadrian
119250008Sadrian    if (q >= p_cap->halTotalQueues) {
120250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q);
121250003Sadrian        return AH_FALSE;
122250003Sadrian    }
123250008Sadrian    return ath_hal_getTxQProps(ah, q_info, &ahp->ah_txq[q]);
124250003Sadrian}
125250003Sadrian
126250003Sadrianenum {
127250003Sadrian    AH_TX_QUEUE_MINUS_OFFSET_BEACON = 1,
128250003Sadrian    AH_TX_QUEUE_MINUS_OFFSET_CAB    = 2,
129250003Sadrian    AH_TX_QUEUE_MINUS_OFFSET_UAPSD  = 3,
130250003Sadrian    AH_TX_QUEUE_MINUS_OFFSET_PAPRD  = 4,
131250003Sadrian};
132250003Sadrian
133250003Sadrian/*
134250003Sadrian * Allocate and initialize a tx DCU/QCU combination.
135250003Sadrian */
136250003Sadrianint
137250003Sadrianar9300_setup_tx_queue(struct ath_hal *ah, HAL_TX_QUEUE type,
138250003Sadrian        const HAL_TXQ_INFO *q_info)
139250003Sadrian{
140250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
141250003Sadrian    HAL_TX_QUEUE_INFO *qi;
142250003Sadrian    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
143250003Sadrian    int q;
144250003Sadrian
145250003Sadrian    /* XXX move queue assignment to driver */
146250003Sadrian    switch (type) {
147250003Sadrian    case HAL_TX_QUEUE_BEACON:
148250003Sadrian        /* highest priority */
149250008Sadrian        q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_BEACON;
150250003Sadrian        break;
151250003Sadrian    case HAL_TX_QUEUE_CAB:
152250003Sadrian        /* next highest priority */
153250008Sadrian        q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_CAB;
154250003Sadrian        break;
155250003Sadrian    case HAL_TX_QUEUE_UAPSD:
156250008Sadrian        q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_UAPSD;
157250003Sadrian        break;
158250003Sadrian    case HAL_TX_QUEUE_PAPRD:
159250008Sadrian        q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_PAPRD;
160250003Sadrian        break;
161250003Sadrian    case HAL_TX_QUEUE_DATA:
162250003Sadrian        /*
163250003Sadrian         * don't infringe on top 4 queues, reserved for:
164250003Sadrian         * beacon, CAB, UAPSD, PAPRD
165250003Sadrian         */
166250003Sadrian        for (q = 0;
167250008Sadrian             q < p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_PAPRD;
168250003Sadrian             q++)
169250003Sadrian        {
170250003Sadrian            if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) {
171250003Sadrian                break;
172250003Sadrian            }
173250003Sadrian        }
174250008Sadrian        if (q == p_cap->halTotalQueues - 3) {
175250003Sadrian            HALDEBUG(ah, HAL_DEBUG_QUEUE,
176250003Sadrian                "%s: no available tx queue\n", __func__);
177250003Sadrian            return -1;
178250003Sadrian        }
179250003Sadrian        break;
180250003Sadrian    default:
181250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
182250003Sadrian            "%s: bad tx queue type %u\n", __func__, type);
183250003Sadrian        return -1;
184250003Sadrian    }
185250003Sadrian
186250003Sadrian    HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: queue %u\n", __func__, q);
187250003Sadrian
188250003Sadrian    qi = &ahp->ah_txq[q];
189250003Sadrian    if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) {
190250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
191250003Sadrian            "%s: tx queue %u already active\n", __func__, q);
192250003Sadrian        return -1;
193250003Sadrian    }
194250003Sadrian
195250003Sadrian    OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO));
196250003Sadrian    qi->tqi_type = type;
197250003Sadrian
198250003Sadrian    if (q_info == AH_NULL) {
199250003Sadrian        /* by default enable OK+ERR+DESC+URN interrupts */
200250008Sadrian        qi->tqi_qflags = HAL_TXQ_TXOKINT_ENABLE
201250008Sadrian                        | HAL_TXQ_TXERRINT_ENABLE
202250008Sadrian                        | HAL_TXQ_TXDESCINT_ENABLE
203250008Sadrian                        | HAL_TXQ_TXURNINT_ENABLE;
204250003Sadrian        qi->tqi_aifs = INIT_AIFS;
205250003Sadrian        qi->tqi_cwmin = HAL_TXQ_USEDEFAULT;     /* NB: do at reset */
206250003Sadrian        qi->tqi_cwmax = INIT_CWMAX;
207250003Sadrian        qi->tqi_shretry = INIT_SH_RETRY;
208250003Sadrian        qi->tqi_lgretry = INIT_LG_RETRY;
209250008Sadrian        qi->tqi_physCompBuf = 0;
210250003Sadrian    } else {
211250008Sadrian        qi->tqi_physCompBuf = q_info->tqi_compBuf;
212250003Sadrian        (void) ar9300_set_tx_queue_props(ah, q, q_info);
213250003Sadrian    }
214250003Sadrian    /* NB: must be followed by ar9300_reset_tx_queue */
215250003Sadrian    return q;
216250003Sadrian}
217250003Sadrian
218250003Sadrian/*
219250003Sadrian * Update the h/w interrupt registers to reflect a tx q's configuration.
220250003Sadrian */
221250003Sadrianstatic void
222250003Sadrianset_tx_q_interrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi)
223250003Sadrian{
224250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
225250003Sadrian
226250003Sadrian    HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
227250003Sadrian            "%s: tx ok 0x%x err 0x%x eol 0x%x urn 0x%x\n",
228250003Sadrian            __func__,
229250003Sadrian            ahp->ah_tx_ok_interrupt_mask,
230250003Sadrian            ahp->ah_tx_err_interrupt_mask,
231250003Sadrian            ahp->ah_tx_eol_interrupt_mask,
232250003Sadrian            ahp->ah_tx_urn_interrupt_mask);
233250003Sadrian
234250003Sadrian    OS_REG_WRITE(ah, AR_IMR_S0,
235250003Sadrian              SM(ahp->ah_tx_ok_interrupt_mask, AR_IMR_S0_QCU_TXOK));
236250003Sadrian    OS_REG_WRITE(ah, AR_IMR_S1,
237250003Sadrian              SM(ahp->ah_tx_err_interrupt_mask, AR_IMR_S1_QCU_TXERR)
238250003Sadrian            | SM(ahp->ah_tx_eol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
239250003Sadrian    OS_REG_RMW_FIELD(ah,
240250003Sadrian        AR_IMR_S2, AR_IMR_S2_QCU_TXURN, ahp->ah_tx_urn_interrupt_mask);
241250003Sadrian    ahp->ah_mask2Reg = OS_REG_READ(ah, AR_IMR_S2);
242250003Sadrian}
243250003Sadrian
244250003Sadrian/*
245250003Sadrian * Free a tx DCU/QCU combination.
246250003Sadrian */
247250003SadrianHAL_BOOL
248250003Sadrianar9300_release_tx_queue(struct ath_hal *ah, u_int q)
249250003Sadrian{
250250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
251250003Sadrian    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
252250003Sadrian    HAL_TX_QUEUE_INFO *qi;
253250003Sadrian
254250008Sadrian    if (q >= p_cap->halTotalQueues) {
255250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q);
256250003Sadrian        return AH_FALSE;
257250003Sadrian    }
258250003Sadrian
259250003Sadrian    qi = &ahp->ah_txq[q];
260250003Sadrian    if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
261250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: inactive queue %u\n", __func__, q);
262250003Sadrian        return AH_FALSE;
263250003Sadrian    }
264250003Sadrian
265250003Sadrian    HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: release queue %u\n", __func__, q);
266250003Sadrian
267250003Sadrian    qi->tqi_type = HAL_TX_QUEUE_INACTIVE;
268250003Sadrian    ahp->ah_tx_ok_interrupt_mask &= ~(1 << q);
269250003Sadrian    ahp->ah_tx_err_interrupt_mask &= ~(1 << q);
270250003Sadrian    ahp->ah_tx_eol_interrupt_mask &= ~(1 << q);
271250003Sadrian    ahp->ah_tx_urn_interrupt_mask &= ~(1 << q);
272250003Sadrian    set_tx_q_interrupts(ah, qi);
273250003Sadrian
274250003Sadrian    return AH_TRUE;
275250003Sadrian}
276250003Sadrian
277250003Sadrian/*
278250003Sadrian * Set the retry, aifs, cwmin/max, ready_time regs for specified queue
279250003Sadrian * Assumes:
280250003Sadrian *  phw_channel has been set to point to the current channel
281250003Sadrian */
282250003SadrianHAL_BOOL
283250003Sadrianar9300_reset_tx_queue(struct ath_hal *ah, u_int q)
284250003Sadrian{
285250003Sadrian    struct ath_hal_9300     *ahp  = AH9300(ah);
286250008Sadrian//    struct ath_hal_private  *ap   = AH_PRIVATE(ah);
287250003Sadrian    HAL_CAPABILITIES        *p_cap = &AH_PRIVATE(ah)->ah_caps;
288250008Sadrian    const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
289250003Sadrian    HAL_TX_QUEUE_INFO       *qi;
290250003Sadrian    u_int32_t               cw_min, chan_cw_min, value;
291301641Sadrian    uint32_t                qmisc, dmisc;
292250003Sadrian
293250008Sadrian    if (q >= p_cap->halTotalQueues) {
294250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q);
295250003Sadrian        return AH_FALSE;
296250003Sadrian    }
297250003Sadrian
298250003Sadrian    qi = &ahp->ah_txq[q];
299250003Sadrian    if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
300250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: inactive queue %u\n", __func__, q);
301250003Sadrian        return AH_TRUE;         /* XXX??? */
302250003Sadrian    }
303250003Sadrian
304250003Sadrian    HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: reset queue %u\n", __func__, q);
305250003Sadrian
306250003Sadrian    if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) {
307250003Sadrian        /*
308250003Sadrian         * Select cwmin according to channel type.
309250003Sadrian         * NB: chan can be NULL during attach
310250003Sadrian         */
311250008Sadrian        if (chan && IEEE80211_IS_CHAN_B(chan)) {
312250003Sadrian            chan_cw_min = INIT_CWMIN_11B;
313250003Sadrian        } else {
314250003Sadrian            chan_cw_min = INIT_CWMIN;
315250003Sadrian        }
316250003Sadrian        /* make sure that the CWmin is of the form (2^n - 1) */
317250003Sadrian        for (cw_min = 1; cw_min < chan_cw_min; cw_min = (cw_min << 1) | 1) {}
318250003Sadrian    } else {
319250003Sadrian        cw_min = qi->tqi_cwmin;
320250003Sadrian    }
321250003Sadrian
322250003Sadrian    /* set cw_min/Max and AIFS values */
323250008Sadrian    if (q > 3 || (!AH9300(ah)->ah_fccaifs))
324250003Sadrian       /* values should not be overwritten if domain is FCC and manual rate
325250003Sadrian         less than 24Mb is set, this check  is making sure this */
326250003Sadrian    {
327250003Sadrian        OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(cw_min, AR_D_LCL_IFS_CWMIN)
328250003Sadrian                | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
329250003Sadrian                | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
330250003Sadrian    }
331250003Sadrian
332250003Sadrian    /* Set retry limit values */
333250003Sadrian    OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q),
334250003Sadrian        SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
335250003Sadrian        SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
336250003Sadrian        SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
337250003Sadrian
338250003Sadrian    /* enable early termination on the QCU */
339301641Sadrian    qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ;
340250003Sadrian
341250003Sadrian    /* enable DCU to wait for next fragment from QCU  */
342250003Sadrian    if (AR_SREV_WASP(ah) && (AH_PRIVATE((ah))->ah_macRev <= AR_SREV_REVISION_WASP_12)) {
343250003Sadrian        /* WAR for EV#85395: Wasp Rx overrun issue - reduces Tx queue backoff
344250003Sadrian         * threshold to 1 to avoid Rx overruns - Fixed in Wasp 1.3 */
345301641Sadrian        dmisc = AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1;
346250003Sadrian    } else {
347301641Sadrian        dmisc = AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2;
348250003Sadrian    }
349250003Sadrian
350250003Sadrian    /* multiqueue support */
351250008Sadrian    if (qi->tqi_cbrPeriod) {
352250003Sadrian        OS_REG_WRITE(ah,
353250003Sadrian            AR_QCBRCFG(q),
354250008Sadrian            SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
355250008Sadrian                SM(qi->tqi_cbrOverflowLimit,
356250003Sadrian            AR_Q_CBRCFG_OVF_THRESH));
357301641Sadrian        qmisc |= AR_Q_MISC_FSP_CBR |
358250008Sadrian            (qi->tqi_cbrOverflowLimit ?
359301641Sadrian                AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0);
360250003Sadrian    }
361250003Sadrian
362250008Sadrian    if (qi->tqi_readyTime && (qi->tqi_type != HAL_TX_QUEUE_CAB)) {
363250003Sadrian        OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
364250008Sadrian            SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
365250003Sadrian            AR_Q_RDYTIMECFG_EN);
366250003Sadrian    }
367250003Sadrian
368250008Sadrian    OS_REG_WRITE(ah, AR_DCHNTIME(q), SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
369250008Sadrian                (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
370250003Sadrian
371302030Sadrian    if (qi->tqi_readyTime &&
372302030Sadrian      (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE))
373301641Sadrian        qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY;
374302030Sadrian    if (qi->tqi_qflags & HAL_TXQ_DBA_GATED)
375302030Sadrian        qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED;
376302030Sadrian    if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) {
377302030Sadrian        /*
378302030Sadrian        * These are meangingful only when not scheduled asap.
379302030Sadrian        */
380302030Sadrian        if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY)
381302030Sadrian            qmisc |= AR_Q_MISC_CBR_INCR_DIS0;
382302030Sadrian        else
383302030Sadrian            qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0;
384302030Sadrian        if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY)
385302030Sadrian            qmisc |= AR_Q_MISC_CBR_INCR_DIS1;
386302030Sadrian        else
387302030Sadrian            qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1;
388250003Sadrian    }
389250003Sadrian
390302030Sadrian    if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE)
391301641Sadrian        dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS;
392302030Sadrian    if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE)
393301641Sadrian        dmisc |= AR_D_MISC_FRAG_BKOFF_EN;
394302030Sadrian    if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL)
395302030Sadrian        dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
396302030Sadrian                    AR_D_MISC_ARB_LOCKOUT_CNTRL);
397302030Sadrian    else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA)
398302030Sadrian        dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR,
399302030Sadrian                    AR_D_MISC_ARB_LOCKOUT_CNTRL);
400302030Sadrian    if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL)
401302030Sadrian        dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE,
402302030Sadrian                    AR_D_MISC_VIR_COL_HANDLING);
403302030Sadrian    if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS)
404302030Sadrian        dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS;
405250003Sadrian
406250003Sadrian    switch (qi->tqi_type) {
407250003Sadrian    case HAL_TX_QUEUE_BEACON:               /* beacon frames */
408301641Sadrian        qmisc |= AR_Q_MISC_FSP_DBA_GATED
409250003Sadrian                    | AR_Q_MISC_BEACON_USE
410301641Sadrian                    | AR_Q_MISC_CBR_INCR_DIS1;
411250003Sadrian
412301641Sadrian        dmisc |= (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
413250003Sadrian                    AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
414250003Sadrian                    | AR_D_MISC_BEACON_USE
415301641Sadrian                    | AR_D_MISC_POST_FR_BKOFF_DIS;
416250003Sadrian        /* XXX cwmin and cwmax should be 0 for beacon queue */
417250003Sadrian        if (AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS) {
418250003Sadrian            OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)
419250003Sadrian                        | SM(0, AR_D_LCL_IFS_CWMAX)
420250003Sadrian                        | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
421250003Sadrian        }
422250003Sadrian        break;
423250003Sadrian    case HAL_TX_QUEUE_CAB:                  /* CAB  frames */
424250003Sadrian        /*
425250003Sadrian         * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY,
426250003Sadrian         * bug #6079.  There is an issue with the CAB Queue
427250003Sadrian         * not properly refreshing the Tx descriptor if
428250003Sadrian         * the TXE clear setting is used.
429250003Sadrian         */
430301641Sadrian        qmisc |= AR_Q_MISC_FSP_DBA_GATED
431250003Sadrian                        | AR_Q_MISC_CBR_INCR_DIS1
432301641Sadrian                        | AR_Q_MISC_CBR_INCR_DIS0;
433250003Sadrian
434301639Sadrian        if (qi->tqi_readyTime) {
435301639Sadrian            OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
436301639Sadrian              SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
437301639Sadrian              AR_Q_RDYTIMECFG_EN);
438301639Sadrian        } else {
439250003Sadrian
440301639Sadrian            value = (ahp->ah_beaconInterval * 50 / 100)
441301639Sadrian              - ah->ah_config.ah_additional_swba_backoff
442301639Sadrian              - ah->ah_config.ah_sw_beacon_response_time
443301639Sadrian              + ah->ah_config.ah_dma_beacon_response_time;
444301639Sadrian            /*
445301639Sadrian             * XXX Ensure it isn't too low - nothing lower
446301639Sadrian             * XXX than 10 TU
447301639Sadrian             */
448301639Sadrian            if (value < 10)
449301639Sadrian                value = 10;
450301639Sadrian            HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
451301639Sadrian              "%s: defaulting to rdytime = %d uS\n",
452301639Sadrian              __func__, value);
453301639Sadrian            OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
454301639Sadrian              SM(TU_TO_USEC(value), AR_Q_RDYTIMECFG_DURATION) |
455301639Sadrian              AR_Q_RDYTIMECFG_EN);
456301639Sadrian        }
457302030Sadrian        dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
458302030Sadrian                    AR_D_MISC_ARB_LOCKOUT_CNTRL);
459250003Sadrian        break;
460250003Sadrian    case HAL_TX_QUEUE_PSPOLL:
461250003Sadrian        /*
462250003Sadrian         * We may configure ps_poll QCU to be TIM-gated in the
463250003Sadrian         * future; TIM_GATED bit is not enabled currently because
464250003Sadrian         * of a hardware problem in Oahu that overshoots the TIM
465250003Sadrian         * bitmap in beacon and may find matching associd bit in
466250003Sadrian         * non-TIM elements and send PS-poll PS poll processing
467250003Sadrian         * will be done in software
468250003Sadrian         */
469301641Sadrian        qmisc |= AR_Q_MISC_CBR_INCR_DIS1;
470250003Sadrian        break;
471250003Sadrian    case HAL_TX_QUEUE_UAPSD:
472301641Sadrian        dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS;
473250003Sadrian        break;
474250003Sadrian    default:                        /* NB: silence compiler */
475250003Sadrian        break;
476250003Sadrian    }
477250003Sadrian
478250003Sadrian#ifndef AH_DISABLE_WME
479250003Sadrian    /*
480250003Sadrian     * Yes, this is a hack and not the right way to do it, but
481250003Sadrian     * it does get the lockout bits and backoff set for the
482250003Sadrian     * high-pri WME queues for testing.  We need to either extend
483250003Sadrian     * the meaning of queue_info->mode, or create something like
484250003Sadrian     * queue_info->dcumode.
485250003Sadrian     */
486250008Sadrian    if (qi->tqi_intFlags & HAL_TXQ_USE_LOCKOUT_BKOFF_DIS) {
487301641Sadrian        dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
488250003Sadrian                    AR_D_MISC_ARB_LOCKOUT_CNTRL) |
489301641Sadrian                AR_D_MISC_POST_FR_BKOFF_DIS;
490250003Sadrian    }
491250003Sadrian#endif
492250003Sadrian
493250003Sadrian    OS_REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
494301641Sadrian    OS_REG_WRITE(ah, AR_QMISC(q), qmisc);
495301641Sadrian    OS_REG_WRITE(ah, AR_DMISC(q), dmisc);
496250003Sadrian
497250003Sadrian    /*
498250003Sadrian     * Always update the secondary interrupt mask registers - this
499250003Sadrian     * could be a new queue getting enabled in a running system or
500250003Sadrian     * hw getting re-initialized during a reset!
501250003Sadrian     *
502250003Sadrian     * Since we don't differentiate between tx interrupts corresponding
503250003Sadrian     * to individual queues - secondary tx mask regs are always unmasked;
504250003Sadrian     * tx interrupts are enabled/disabled for all queues collectively
505250003Sadrian     * using the primary mask reg
506250003Sadrian     */
507250008Sadrian    if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) {
508250003Sadrian        ahp->ah_tx_ok_interrupt_mask |=  (1 << q);
509250003Sadrian    } else {
510250003Sadrian        ahp->ah_tx_ok_interrupt_mask &= ~(1 << q);
511250003Sadrian    }
512250008Sadrian    if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) {
513250003Sadrian        ahp->ah_tx_err_interrupt_mask |=  (1 << q);
514250003Sadrian    } else {
515250003Sadrian        ahp->ah_tx_err_interrupt_mask &= ~(1 << q);
516250003Sadrian    }
517250008Sadrian    if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) {
518250003Sadrian        ahp->ah_tx_eol_interrupt_mask |=  (1 << q);
519250003Sadrian    } else {
520250003Sadrian        ahp->ah_tx_eol_interrupt_mask &= ~(1 << q);
521250003Sadrian    }
522250008Sadrian    if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) {
523250003Sadrian        ahp->ah_tx_urn_interrupt_mask |=  (1 << q);
524250003Sadrian    } else {
525250003Sadrian        ahp->ah_tx_urn_interrupt_mask &= ~(1 << q);
526250003Sadrian    }
527250003Sadrian    set_tx_q_interrupts(ah, qi);
528250003Sadrian
529250003Sadrian    return AH_TRUE;
530250003Sadrian}
531250003Sadrian
532250003Sadrian/*
533250003Sadrian * Get the TXDP for the specified queue
534250003Sadrian */
535250003Sadrianu_int32_t
536250003Sadrianar9300_get_tx_dp(struct ath_hal *ah, u_int q)
537250003Sadrian{
538250008Sadrian    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
539250003Sadrian    return OS_REG_READ(ah, AR_QTXDP(q));
540250003Sadrian}
541250003Sadrian
542250003Sadrian/*
543250003Sadrian * Set the tx_dp for the specified queue
544250003Sadrian */
545250003SadrianHAL_BOOL
546250003Sadrianar9300_set_tx_dp(struct ath_hal *ah, u_int q, u_int32_t txdp)
547250003Sadrian{
548250008Sadrian    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
549250003Sadrian    HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
550250003Sadrian    HALASSERT(txdp != 0);
551250003Sadrian
552250003Sadrian    OS_REG_WRITE(ah, AR_QTXDP(q), txdp);
553250003Sadrian
554250003Sadrian    return AH_TRUE;
555250003Sadrian}
556250003Sadrian
557250003Sadrian/*
558250003Sadrian * Transmit Enable is read-only now
559250003Sadrian */
560250003SadrianHAL_BOOL
561250003Sadrianar9300_start_tx_dma(struct ath_hal *ah, u_int q)
562250003Sadrian{
563250003Sadrian    return AH_TRUE;
564250003Sadrian}
565250003Sadrian
566250003Sadrian/*
567250003Sadrian * Return the number of pending frames or 0 if the specified
568250003Sadrian * queue is stopped.
569250003Sadrian */
570250003Sadrianu_int32_t
571250003Sadrianar9300_num_tx_pending(struct ath_hal *ah, u_int q)
572250003Sadrian{
573250003Sadrian    u_int32_t npend;
574250003Sadrian
575250008Sadrian    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
576250003Sadrian
577250003Sadrian    npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
578250003Sadrian    if (npend == 0) {
579250003Sadrian        /*
580250003Sadrian         * Pending frame count (PFC) can momentarily go to zero
581250003Sadrian         * while TXE remains asserted.  In other words a PFC of
582250003Sadrian         * zero is not sufficient to say that the queue has stopped.
583250003Sadrian         */
584250003Sadrian        if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) {
585250003Sadrian            npend = 1;              /* arbitrarily return 1 */
586250003Sadrian        }
587250003Sadrian    }
588250003Sadrian#ifdef DEBUG
589250003Sadrian    if (npend && (AH9300(ah)->ah_txq[q].tqi_type == HAL_TX_QUEUE_CAB)) {
590250003Sadrian        if (OS_REG_READ(ah, AR_Q_RDYTIMESHDN) & (1 << q)) {
591250003Sadrian            HALDEBUG(ah, HAL_DEBUG_QUEUE, "RTSD on CAB queue\n");
592250003Sadrian            /* Clear the ready_time shutdown status bits */
593250003Sadrian            OS_REG_WRITE(ah, AR_Q_RDYTIMESHDN, 1 << q);
594250003Sadrian        }
595250003Sadrian    }
596250003Sadrian#endif
597250003Sadrian    HALASSERT((npend == 0) ||
598250003Sadrian        (AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE));
599250003Sadrian
600250003Sadrian    return npend;
601250003Sadrian}
602250003Sadrian
603250003Sadrian/*
604250003Sadrian * Stop transmit on the specified queue
605250003Sadrian */
606250003SadrianHAL_BOOL
607250003Sadrianar9300_stop_tx_dma(struct ath_hal *ah, u_int q, u_int timeout)
608250003Sadrian{
609278741Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
610278741Sadrian
611250003Sadrian    /*
612278741Sadrian     * If we call abort txdma instead, no need to stop RX.
613278741Sadrian     * Otherwise, the RX logic might not be restarted properly.
614278741Sadrian     */
615278741Sadrian    ahp->ah_abort_txdma_norx = AH_FALSE;
616278741Sadrian
617278741Sadrian    /*
618250003Sadrian     * Directly call abort.  It is better, hardware-wise, to stop all
619250003Sadrian     * queues at once than individual ones.
620250003Sadrian     */
621250003Sadrian    return ar9300_abort_tx_dma(ah);
622250003Sadrian
623250003Sadrian#if 0
624250003Sadrian#define AH_TX_STOP_DMA_TIMEOUT 4000    /* usec */
625250003Sadrian#define AH_TIME_QUANTUM        100     /* usec */
626250003Sadrian    u_int wait;
627250003Sadrian
628250003Sadrian    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues);
629250003Sadrian
630250003Sadrian    HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
631250003Sadrian
632250003Sadrian    if (timeout == 0) {
633250003Sadrian        timeout = AH_TX_STOP_DMA_TIMEOUT;
634250003Sadrian    }
635250003Sadrian
636250003Sadrian    OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
637250003Sadrian
638250003Sadrian    for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
639250003Sadrian        if (ar9300_num_tx_pending(ah, q) == 0) {
640250003Sadrian            break;
641250003Sadrian        }
642250003Sadrian        OS_DELAY(AH_TIME_QUANTUM);        /* XXX get actual value */
643250003Sadrian    }
644250003Sadrian
645250003Sadrian#ifdef AH_DEBUG
646250003Sadrian    if (wait == 0) {
647250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
648250003Sadrian            "%s: queue %u DMA did not stop in 100 msec\n", __func__, q);
649250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
650250003Sadrian            "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n",
651250003Sadrian            __func__,
652250003Sadrian            OS_REG_READ(ah, AR_QSTS(q)),
653250003Sadrian            OS_REG_READ(ah, AR_Q_TXE),
654250003Sadrian            OS_REG_READ(ah, AR_Q_TXD),
655250003Sadrian            OS_REG_READ(ah, AR_QCBRCFG(q)));
656250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
657250003Sadrian            "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",
658250003Sadrian            __func__,
659250003Sadrian            OS_REG_READ(ah, AR_QMISC(q)),
660250003Sadrian            OS_REG_READ(ah, AR_QRDYTIMECFG(q)),
661250003Sadrian            OS_REG_READ(ah, AR_Q_RDYTIMESHDN));
662250003Sadrian    }
663250003Sadrian#endif /* AH_DEBUG */
664250003Sadrian
665250003Sadrian    /* 2413+ and up can kill packets at the PCU level */
666250003Sadrian    if (ar9300_num_tx_pending(ah, q)) {
667250003Sadrian        u_int32_t tsf_low, j;
668250003Sadrian
669250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Num of pending TX Frames %d on Q %d\n",
670250003Sadrian                 __func__, ar9300_num_tx_pending(ah, q), q);
671250003Sadrian
672250003Sadrian        /* Kill last PCU Tx Frame */
673250003Sadrian        /* TODO - save off and restore current values of Q1/Q2? */
674250003Sadrian        for (j = 0; j < 2; j++) {
675250003Sadrian            tsf_low = OS_REG_READ(ah, AR_TSF_L32);
676250003Sadrian            OS_REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR));
677250003Sadrian            OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100);
678250003Sadrian            OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsf_low >> 10);
679250003Sadrian            OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
680250003Sadrian
681250003Sadrian            if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsf_low >> 10)) {
682250003Sadrian                break;
683250003Sadrian            }
684250003Sadrian
685250003Sadrian            HALDEBUG(ah, HAL_DEBUG_QUEUE,
686250003Sadrian                "%s: TSF have moved while trying to set "
687250003Sadrian                "quiet time TSF: 0x%08x\n",
688250003Sadrian                __func__, tsf_low);
689250003Sadrian            /* TSF shouldn't count twice or reg access is taking forever */
690250003Sadrian            HALASSERT(j < 1);
691250003Sadrian        }
692250003Sadrian
693250003Sadrian        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
694250003Sadrian
695250003Sadrian        /* Allow the quiet mechanism to do its work */
696250003Sadrian        OS_DELAY(200);
697250003Sadrian        OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
698250003Sadrian
699250003Sadrian        /* Verify all transmit is dead */
700250003Sadrian        wait = timeout / AH_TIME_QUANTUM;
701250003Sadrian        while (ar9300_num_tx_pending(ah, q)) {
702250003Sadrian            if ((--wait) == 0) {
703250003Sadrian                HALDEBUG(ah, HAL_DEBUG_TX,
704250003Sadrian                    "%s: Failed to stop Tx DMA in %d msec "
705250003Sadrian                    "after killing last frame\n",
706250003Sadrian                    __func__, timeout / 1000);
707250003Sadrian                break;
708250003Sadrian            }
709250003Sadrian            OS_DELAY(AH_TIME_QUANTUM);
710250003Sadrian        }
711250003Sadrian
712250003Sadrian        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
713250003Sadrian    }
714250003Sadrian
715250003Sadrian    OS_REG_WRITE(ah, AR_Q_TXD, 0);
716250003Sadrian    return (wait != 0);
717250003Sadrian
718250003Sadrian#undef AH_TX_STOP_DMA_TIMEOUT
719250003Sadrian#undef AH_TIME_QUANTUM
720250003Sadrian#endif
721250003Sadrian}
722250003Sadrian
723250003Sadrian/*
724250003Sadrian * Really Stop transmit on the specified queue
725250003Sadrian */
726250003SadrianHAL_BOOL
727250003Sadrianar9300_stop_tx_dma_indv_que(struct ath_hal *ah, u_int q, u_int timeout)
728250003Sadrian{
729250003Sadrian#define AH_TX_STOP_DMA_TIMEOUT 4000    /* usec */
730250003Sadrian#define AH_TIME_QUANTUM        100     /* usec */
731250003Sadrian    u_int wait;
732250003Sadrian
733250003Sadrian    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues);
734250003Sadrian
735250003Sadrian    HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
736250003Sadrian
737250003Sadrian    if (timeout == 0) {
738250003Sadrian        timeout = AH_TX_STOP_DMA_TIMEOUT;
739250003Sadrian    }
740250003Sadrian
741250003Sadrian    OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
742250003Sadrian
743250003Sadrian    for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
744250003Sadrian        if (ar9300_num_tx_pending(ah, q) == 0) {
745250003Sadrian            break;
746250003Sadrian        }
747250003Sadrian        OS_DELAY(AH_TIME_QUANTUM);        /* XXX get actual value */
748250003Sadrian    }
749250003Sadrian
750250003Sadrian#ifdef AH_DEBUG
751250003Sadrian    if (wait == 0) {
752250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
753250003Sadrian            "%s: queue %u DMA did not stop in 100 msec\n", __func__, q);
754250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
755250003Sadrian            "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n",
756250003Sadrian            __func__,
757250003Sadrian            OS_REG_READ(ah, AR_QSTS(q)),
758250003Sadrian            OS_REG_READ(ah, AR_Q_TXE),
759250003Sadrian            OS_REG_READ(ah, AR_Q_TXD),
760250003Sadrian            OS_REG_READ(ah, AR_QCBRCFG(q)));
761250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE,
762250003Sadrian            "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",
763250003Sadrian            __func__,
764250003Sadrian            OS_REG_READ(ah, AR_QMISC(q)),
765250003Sadrian            OS_REG_READ(ah, AR_QRDYTIMECFG(q)),
766250003Sadrian            OS_REG_READ(ah, AR_Q_RDYTIMESHDN));
767250003Sadrian    }
768250003Sadrian#endif /* AH_DEBUG */
769250003Sadrian
770250003Sadrian    /* 2413+ and up can kill packets at the PCU level */
771250003Sadrian    if (ar9300_num_tx_pending(ah, q)) {
772250003Sadrian        u_int32_t tsf_low, j;
773250003Sadrian
774250003Sadrian        HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Num of pending TX Frames %d on Q %d\n",
775250003Sadrian                 __func__, ar9300_num_tx_pending(ah, q), q);
776250003Sadrian
777250003Sadrian        /* Kill last PCU Tx Frame */
778250003Sadrian        /* TODO - save off and restore current values of Q1/Q2? */
779250003Sadrian        for (j = 0; j < 2; j++) {
780250003Sadrian            tsf_low = OS_REG_READ(ah, AR_TSF_L32);
781250003Sadrian            OS_REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR));
782250003Sadrian            OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100);
783250003Sadrian            OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsf_low >> 10);
784250003Sadrian            OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
785250003Sadrian
786250003Sadrian            if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsf_low >> 10)) {
787250003Sadrian                break;
788250003Sadrian            }
789250003Sadrian
790250003Sadrian            HALDEBUG(ah, HAL_DEBUG_QUEUE,
791250003Sadrian                "%s: TSF have moved while trying to set "
792250003Sadrian                "quiet time TSF: 0x%08x\n",
793250003Sadrian                __func__, tsf_low);
794250003Sadrian            /* TSF shouldn't count twice or reg access is taking forever */
795250003Sadrian            HALASSERT(j < 1);
796250003Sadrian        }
797250003Sadrian
798250003Sadrian        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
799250003Sadrian
800250003Sadrian        /* Allow the quiet mechanism to do its work */
801250003Sadrian        OS_DELAY(200);
802250003Sadrian        OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
803250003Sadrian
804250003Sadrian        /* Verify all transmit is dead */
805250003Sadrian        wait = timeout / AH_TIME_QUANTUM;
806250003Sadrian        while (ar9300_num_tx_pending(ah, q)) {
807250003Sadrian            if ((--wait) == 0) {
808250003Sadrian                HALDEBUG(ah, HAL_DEBUG_TX,
809250003Sadrian                    "%s: Failed to stop Tx DMA in %d msec "
810250003Sadrian                    "after killing last frame\n",
811250003Sadrian                    __func__, timeout / 1000);
812250003Sadrian                break;
813250003Sadrian            }
814250003Sadrian            OS_DELAY(AH_TIME_QUANTUM);
815250003Sadrian        }
816250003Sadrian
817250003Sadrian        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
818250003Sadrian    }
819250003Sadrian
820250003Sadrian    OS_REG_WRITE(ah, AR_Q_TXD, 0);
821250003Sadrian    return (wait != 0);
822250003Sadrian
823250003Sadrian#undef AH_TX_STOP_DMA_TIMEOUT
824250003Sadrian#undef AH_TIME_QUANTUM
825250003Sadrian}
826250003Sadrian
827250003Sadrian/*
828250003Sadrian * Abort transmit on all queues
829250003Sadrian */
830250003Sadrian#define AR9300_ABORT_LOOPS     1000
831250003Sadrian#define AR9300_ABORT_WAIT      5
832278741Sadrian#define NEXT_TBTT_NOW       10
833250003SadrianHAL_BOOL
834250003Sadrianar9300_abort_tx_dma(struct ath_hal *ah)
835250003Sadrian{
836278741Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
837250003Sadrian    int i, q;
838278741Sadrian    u_int32_t nexttbtt, nextdba, tsf_tbtt, tbtt, dba;
839278741Sadrian    HAL_BOOL stopped;
840278741Sadrian    HAL_BOOL status = AH_TRUE;
841250003Sadrian
842278741Sadrian    if (ahp->ah_abort_txdma_norx) {
843278741Sadrian        /*
844278741Sadrian         * First of all, make sure RX has been stopped
845278741Sadrian         */
846278741Sadrian        if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) {
847278741Sadrian            /* Need to stop RX DMA before reset otherwise chip might hang */
848278741Sadrian            stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */
849278741Sadrian            ar9300_set_rx_filter(ah, 0);
850278741Sadrian            stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */
851278741Sadrian            if (!stopped) {
852278741Sadrian                /*
853278741Sadrian                 * During the transition from full sleep to reset,
854278741Sadrian                 * recv DMA regs are not available to be read
855278741Sadrian                 */
856278741Sadrian                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
857278741Sadrian                    "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__);
858278741Sadrian                //We still continue to stop TX dma
859278741Sadrian                //return AH_FALSE;
860278741Sadrian            }
861278741Sadrian        } else {
862278741Sadrian            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
863278741Sadrian                "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__);
864278741Sadrian        }
865278741Sadrian    }
866278741Sadrian
867250003Sadrian    /*
868250003Sadrian     * set txd on all queues
869250003Sadrian     */
870250003Sadrian    OS_REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
871250003Sadrian
872250003Sadrian    /*
873250003Sadrian     * set tx abort bits (also disable rx)
874250003Sadrian     */
875250003Sadrian    OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
876278741Sadrian    /* Add a new receipe from K31 code */
877278741Sadrian    OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS |
878278741Sadrian                                   AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
879278741Sadrian     /* beacon Q flush */
880278741Sadrian    nexttbtt = OS_REG_READ(ah, AR_NEXT_TBTT_TIMER);
881278741Sadrian    nextdba = OS_REG_READ(ah, AR_NEXT_DMA_BEACON_ALERT);
882278741Sadrian    //printk("%s[%d]:dba: %d, nt: %d \n", __func__, __LINE__, nextdba, nexttbtt);
883278741Sadrian    tsf_tbtt =  OS_REG_READ(ah, AR_TSF_L32);
884278741Sadrian    tbtt = tsf_tbtt + NEXT_TBTT_NOW;
885278741Sadrian    dba = tsf_tbtt;
886278741Sadrian    OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, dba);
887278741Sadrian    OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, tbtt);
888250003Sadrian    OS_REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
889250003Sadrian
890278741Sadrian    /*
891278741Sadrian     * Let TXE (all queues) clear before waiting for any pending frames
892278741Sadrian     * This is needed before starting the RF_BUS GRANT sequence other wise causes kernel
893278741Sadrian     * panic
894278741Sadrian     */
895278741Sadrian    for(i = 0; i < AR9300_ABORT_LOOPS; i++) {
896278741Sadrian        if(OS_REG_READ(ah, AR_Q_TXE) == 0) {
897250003Sadrian            break;
898250003Sadrian        }
899250003Sadrian        OS_DELAY(AR9300_ABORT_WAIT);
900250003Sadrian    }
901250003Sadrian    if (i == AR9300_ABORT_LOOPS) {
902250003Sadrian        HALDEBUG(ah, HAL_DEBUG_TX, "%s[%d] reached max wait on TXE\n",
903250003Sadrian                 __func__, __LINE__);
904250003Sadrian    }
905250003Sadrian
906250003Sadrian    /*
907250003Sadrian     * wait on all tx queues
908278741Sadrian     * This need to be checked in the last to gain extra 50 usec. on avg.
909278741Sadrian     * Currently checked first since we dont have a previous channel information currently.
910278741Sadrian     * Which is needed to revert the rf changes.
911250003Sadrian     */
912278741Sadrian    for (q = AR_NUM_QCU - 1; q >= 0; q--) {
913250003Sadrian        for (i = 0; i < AR9300_ABORT_LOOPS; i++) {
914278741Sadrian            if (!(ar9300_num_tx_pending(ah, q))) {
915250003Sadrian                break;
916250003Sadrian            }
917250003Sadrian            OS_DELAY(AR9300_ABORT_WAIT);
918250003Sadrian        }
919250003Sadrian        if (i == AR9300_ABORT_LOOPS) {
920278741Sadrian            status = AH_FALSE;
921278741Sadrian            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
922278741Sadrian                    "ABORT LOOP finsihsed for Q: %d, num_pending: %d \n",
923278741Sadrian                    q, ar9300_num_tx_pending(ah, q));
924278741Sadrian            goto exit;
925250003Sadrian        }
926250003Sadrian    }
927250003Sadrian
928278741Sadrian    /* Updating the beacon alert register with correct value */
929278741Sadrian    OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, nextdba);
930278741Sadrian    OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, nexttbtt);
931278741Sadrian
932278741Sadrianexit:
933250003Sadrian    /*
934250003Sadrian     * clear tx abort bits
935250003Sadrian     */
936250003Sadrian    OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
937278741Sadrian    /* Added a new receipe from K31 code */
938278741Sadrian    OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS |
939278741Sadrian                                   AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
940250003Sadrian    OS_REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
941250003Sadrian
942250003Sadrian    /*
943250003Sadrian     * clear txd
944250003Sadrian     */
945250003Sadrian    OS_REG_WRITE(ah, AR_Q_TXD, 0);
946250003Sadrian
947278741Sadrian    ahp->ah_abort_txdma_norx = AH_TRUE;
948278741Sadrian
949278741Sadrian    return status;
950250003Sadrian}
951250003Sadrian
952250003Sadrian/*
953250003Sadrian * Determine which tx queues need interrupt servicing.
954250003Sadrian */
955250003Sadrianvoid
956250003Sadrianar9300_get_tx_intr_queue(struct ath_hal *ah, u_int32_t *txqs)
957250003Sadrian{
958250003Sadrian    HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
959250003Sadrian                 "ar9300_get_tx_intr_queue: Should not be called\n");
960250003Sadrian#if 0
961250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
962250003Sadrian    *txqs &= ahp->ah_intr_txqs;
963250003Sadrian    ahp->ah_intr_txqs &= ~(*txqs);
964250003Sadrian#endif
965250003Sadrian}
966250003Sadrian
967250003Sadrianvoid
968250003Sadrianar9300_reset_tx_status_ring(struct ath_hal *ah)
969250003Sadrian{
970250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
971250003Sadrian
972250003Sadrian    ahp->ts_tail = 0;
973250003Sadrian
974250003Sadrian    /* Zero out the status descriptors */
975250003Sadrian    OS_MEMZERO((void *)ahp->ts_ring, ahp->ts_size * sizeof(struct ar9300_txs));
976250003Sadrian    HALDEBUG(ah, HAL_DEBUG_QUEUE,
977250003Sadrian        "%s: TS Start 0x%x End 0x%x Virt %p, Size %d\n", __func__,
978250003Sadrian        ahp->ts_paddr_start, ahp->ts_paddr_end, ahp->ts_ring, ahp->ts_size);
979250003Sadrian
980250003Sadrian    OS_REG_WRITE(ah, AR_Q_STATUS_RING_START, ahp->ts_paddr_start);
981250003Sadrian    OS_REG_WRITE(ah, AR_Q_STATUS_RING_END, ahp->ts_paddr_end);
982250003Sadrian}
983250003Sadrian
984250003Sadrianvoid
985250003Sadrianar9300_setup_tx_status_ring(struct ath_hal *ah, void *ts_start,
986250003Sadrian    u_int32_t ts_paddr_start, u_int16_t size)
987250003Sadrian{
988250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
989250003Sadrian
990250003Sadrian    ahp->ts_paddr_start = ts_paddr_start;
991250003Sadrian    ahp->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9300_txs));
992250003Sadrian    ahp->ts_size = size;
993250003Sadrian    ahp->ts_ring = (struct ar9300_txs *)ts_start;
994250003Sadrian
995250003Sadrian    ar9300_reset_tx_status_ring(ah);
996250003Sadrian}
997