ath9k: do not call ath9k_hw_txprocdesc on AR9003 outside of the tx tasklet
[linux-2.6-block.git] / drivers / net / wireless / ath / ath9k / mac.c
CommitLineData
f1dc5600 1/*
5b68138e 2 * Copyright (c) 2008-2011 Atheros Communications Inc.
f1dc5600
S
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
990b70ab 17#include "hw.h"
ac0bb767 18#include "hw-ops.h"
ee40fa06 19#include <linux/export.h>
f1dc5600 20
cc610ac0
VT
21static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
22 struct ath9k_tx_queue_info *qi)
23{
d2182b69 24 ath_dbg(ath9k_hw_common(ah), INTERRUPT,
226afe68
JP
25 "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
26 ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
27 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
28 ah->txurn_interrupt_mask);
cc610ac0 29
7d0d0df0
S
30 ENABLE_REGWRITE_BUFFER(ah);
31
cc610ac0
VT
32 REG_WRITE(ah, AR_IMR_S0,
33 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
34 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
35 REG_WRITE(ah, AR_IMR_S1,
36 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
37 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
38
39 ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
40 ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
41 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
7d0d0df0
S
42
43 REGWRITE_BUFFER_FLUSH(ah);
cc610ac0
VT
44}
45
46u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
47{
48 return REG_READ(ah, AR_QTXDP(q));
49}
50EXPORT_SYMBOL(ath9k_hw_gettxbuf);
51
52void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
53{
54 REG_WRITE(ah, AR_QTXDP(q), txdp);
55}
56EXPORT_SYMBOL(ath9k_hw_puttxbuf);
57
58void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
59{
d2182b69 60 ath_dbg(ath9k_hw_common(ah), QUEUE, "Enable TXE on queue: %u\n", q);
cc610ac0
VT
61 REG_WRITE(ah, AR_Q_TXE, 1 << q);
62}
63EXPORT_SYMBOL(ath9k_hw_txstart);
64
cc610ac0
VT
65u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
66{
67 u32 npend;
68
69 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
70 if (npend == 0) {
71
72 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
73 npend = 1;
74 }
75
76 return npend;
77}
78EXPORT_SYMBOL(ath9k_hw_numtxpending);
79
80/**
81 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
82 *
83 * @ah: atheros hardware struct
84 * @bIncTrigLevel: whether or not the frame trigger level should be updated
85 *
86 * The frame trigger level specifies the minimum number of bytes,
87 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
88 * before the PCU will initiate sending the frame on the air. This can
89 * mean we initiate transmit before a full frame is on the PCU TX FIFO.
90 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
91 * first)
92 *
93 * Caution must be taken to ensure to set the frame trigger level based
94 * on the DMA request size. For example if the DMA request size is set to
95 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
96 * there need to be enough space in the tx FIFO for the requested transfer
97 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
98 * the threshold to a value beyond 6, then the transmit will hang.
99 *
100 * Current dual stream devices have a PCU TX FIFO size of 8 KB.
101 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
102 * there is a hardware issue which forces us to use 2 KB instead so the
103 * frame trigger level must not exceed 2 KB for these chipsets.
104 */
105bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
106{
107 u32 txcfg, curLevel, newLevel;
cc610ac0
VT
108
109 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
110 return false;
111
4df3071e 112 ath9k_hw_disable_interrupts(ah);
cc610ac0
VT
113
114 txcfg = REG_READ(ah, AR_TXCFG);
115 curLevel = MS(txcfg, AR_FTRIG);
116 newLevel = curLevel;
117 if (bIncTrigLevel) {
118 if (curLevel < ah->config.max_txtrig_level)
119 newLevel++;
120 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
121 newLevel--;
122 if (newLevel != curLevel)
123 REG_WRITE(ah, AR_TXCFG,
124 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
125
4df3071e 126 ath9k_hw_enable_interrupts(ah);
cc610ac0
VT
127
128 ah->tx_trig_level = newLevel;
129
130 return newLevel != curLevel;
131}
132EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
133
0d51cccc 134void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
cc610ac0 135{
0d51cccc 136 int i, q;
cc610ac0 137
0d51cccc 138 REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
cc610ac0 139
0d51cccc
FF
140 REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
141 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
142 REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
cc610ac0 143
0d51cccc
FF
144 for (q = 0; q < AR_NUM_QCU; q++) {
145 for (i = 0; i < 1000; i++) {
146 if (i)
147 udelay(5);
cc610ac0 148
0d51cccc 149 if (!ath9k_hw_numtxpending(ah, q))
cc610ac0 150 break;
cc610ac0 151 }
0d51cccc 152 }
cc610ac0 153
0d51cccc
FF
154 REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
155 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
156 REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
cc610ac0 157
0d51cccc
FF
158 REG_WRITE(ah, AR_Q_TXD, 0);
159}
160EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
cc610ac0 161
efff395e 162bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
cc610ac0 163{
efff395e 164#define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */
cc610ac0 165#define ATH9K_TIME_QUANTUM 100 /* usec */
efff395e
FF
166 int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
167 int wait;
cc610ac0
VT
168
169 REG_WRITE(ah, AR_Q_TXD, 1 << q);
170
171 for (wait = wait_time; wait != 0; wait--) {
efff395e 172 if (wait != wait_time)
cc610ac0 173 udelay(ATH9K_TIME_QUANTUM);
cc610ac0 174
efff395e
FF
175 if (ath9k_hw_numtxpending(ah, q) == 0)
176 break;
cc610ac0
VT
177 }
178
179 REG_WRITE(ah, AR_Q_TXD, 0);
efff395e 180
cc610ac0
VT
181 return wait != 0;
182
183#undef ATH9K_TX_STOP_DMA_TIMEOUT
184#undef ATH9K_TIME_QUANTUM
185}
efff395e 186EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
cc610ac0 187
cbe61d8a 188void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
f1dc5600 189{
2660b81a
S
190 *txqs &= ah->intr_txqs;
191 ah->intr_txqs &= ~(*txqs);
f1dc5600 192}
7322fd19 193EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs);
f1dc5600 194
cbe61d8a 195bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
f1dc5600
S
196 const struct ath9k_tx_queue_info *qinfo)
197{
198 u32 cw;
c46917bb 199 struct ath_common *common = ath9k_hw_common(ah);
f1dc5600
S
200 struct ath9k_tx_queue_info *qi;
201
2660b81a 202 qi = &ah->txq[q];
f1dc5600 203 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
d2182b69 204 ath_dbg(common, QUEUE,
226afe68 205 "Set TXQ properties, inactive queue: %u\n", q);
f1dc5600
S
206 return false;
207 }
208
d2182b69 209 ath_dbg(common, QUEUE, "Set queue properties for: %u\n", q);
f1dc5600
S
210
211 qi->tqi_ver = qinfo->tqi_ver;
212 qi->tqi_subtype = qinfo->tqi_subtype;
213 qi->tqi_qflags = qinfo->tqi_qflags;
214 qi->tqi_priority = qinfo->tqi_priority;
215 if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
216 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
217 else
218 qi->tqi_aifs = INIT_AIFS;
219 if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
220 cw = min(qinfo->tqi_cwmin, 1024U);
221 qi->tqi_cwmin = 1;
222 while (qi->tqi_cwmin < cw)
223 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
224 } else
225 qi->tqi_cwmin = qinfo->tqi_cwmin;
226 if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
227 cw = min(qinfo->tqi_cwmax, 1024U);
228 qi->tqi_cwmax = 1;
229 while (qi->tqi_cwmax < cw)
230 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
231 } else
232 qi->tqi_cwmax = INIT_CWMAX;
233
234 if (qinfo->tqi_shretry != 0)
235 qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
236 else
237 qi->tqi_shretry = INIT_SH_RETRY;
238 if (qinfo->tqi_lgretry != 0)
239 qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
240 else
241 qi->tqi_lgretry = INIT_LG_RETRY;
242 qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
243 qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
244 qi->tqi_burstTime = qinfo->tqi_burstTime;
245 qi->tqi_readyTime = qinfo->tqi_readyTime;
246
247 switch (qinfo->tqi_subtype) {
248 case ATH9K_WME_UPSD:
249 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
250 qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
251 break;
252 default:
253 break;
254 }
255
256 return true;
257}
7322fd19 258EXPORT_SYMBOL(ath9k_hw_set_txq_props);
f1dc5600 259
cbe61d8a 260bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
f1dc5600
S
261 struct ath9k_tx_queue_info *qinfo)
262{
c46917bb 263 struct ath_common *common = ath9k_hw_common(ah);
f1dc5600
S
264 struct ath9k_tx_queue_info *qi;
265
2660b81a 266 qi = &ah->txq[q];
f1dc5600 267 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
d2182b69 268 ath_dbg(common, QUEUE,
226afe68 269 "Get TXQ properties, inactive queue: %u\n", q);
f1dc5600
S
270 return false;
271 }
272
273 qinfo->tqi_qflags = qi->tqi_qflags;
274 qinfo->tqi_ver = qi->tqi_ver;
275 qinfo->tqi_subtype = qi->tqi_subtype;
276 qinfo->tqi_qflags = qi->tqi_qflags;
277 qinfo->tqi_priority = qi->tqi_priority;
278 qinfo->tqi_aifs = qi->tqi_aifs;
279 qinfo->tqi_cwmin = qi->tqi_cwmin;
280 qinfo->tqi_cwmax = qi->tqi_cwmax;
281 qinfo->tqi_shretry = qi->tqi_shretry;
282 qinfo->tqi_lgretry = qi->tqi_lgretry;
283 qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
284 qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
285 qinfo->tqi_burstTime = qi->tqi_burstTime;
286 qinfo->tqi_readyTime = qi->tqi_readyTime;
287
288 return true;
289}
7322fd19 290EXPORT_SYMBOL(ath9k_hw_get_txq_props);
f1dc5600 291
cbe61d8a 292int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
f1dc5600
S
293 const struct ath9k_tx_queue_info *qinfo)
294{
c46917bb 295 struct ath_common *common = ath9k_hw_common(ah);
f1dc5600 296 struct ath9k_tx_queue_info *qi;
f1dc5600
S
297 int q;
298
299 switch (type) {
300 case ATH9K_TX_QUEUE_BEACON:
f4c607dc 301 q = ATH9K_NUM_TX_QUEUES - 1;
f1dc5600
S
302 break;
303 case ATH9K_TX_QUEUE_CAB:
f4c607dc 304 q = ATH9K_NUM_TX_QUEUES - 2;
f1dc5600
S
305 break;
306 case ATH9K_TX_QUEUE_PSPOLL:
307 q = 1;
308 break;
309 case ATH9K_TX_QUEUE_UAPSD:
f4c607dc 310 q = ATH9K_NUM_TX_QUEUES - 3;
f1dc5600
S
311 break;
312 case ATH9K_TX_QUEUE_DATA:
f4c607dc 313 for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
2660b81a 314 if (ah->txq[q].tqi_type ==
f1dc5600
S
315 ATH9K_TX_QUEUE_INACTIVE)
316 break;
f4c607dc 317 if (q == ATH9K_NUM_TX_QUEUES) {
3800276a 318 ath_err(common, "No available TX queue\n");
f1dc5600
S
319 return -1;
320 }
321 break;
322 default:
3800276a 323 ath_err(common, "Invalid TX queue type: %u\n", type);
f1dc5600
S
324 return -1;
325 }
326
d2182b69 327 ath_dbg(common, QUEUE, "Setup TX queue: %u\n", q);
f1dc5600 328
2660b81a 329 qi = &ah->txq[q];
f1dc5600 330 if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
3800276a 331 ath_err(common, "TX queue: %u already active\n", q);
f1dc5600
S
332 return -1;
333 }
334 memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
335 qi->tqi_type = type;
479c6892
RM
336 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
337 (void) ath9k_hw_set_txq_props(ah, q, qinfo);
f1dc5600
S
338
339 return q;
340}
7322fd19 341EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
f1dc5600 342
cbe61d8a 343bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
f1dc5600 344{
c46917bb 345 struct ath_common *common = ath9k_hw_common(ah);
f1dc5600
S
346 struct ath9k_tx_queue_info *qi;
347
2660b81a 348 qi = &ah->txq[q];
f1dc5600 349 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
d2182b69 350 ath_dbg(common, QUEUE, "Release TXQ, inactive queue: %u\n", q);
f1dc5600
S
351 return false;
352 }
353
d2182b69 354 ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);
f1dc5600
S
355
356 qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
2660b81a
S
357 ah->txok_interrupt_mask &= ~(1 << q);
358 ah->txerr_interrupt_mask &= ~(1 << q);
359 ah->txdesc_interrupt_mask &= ~(1 << q);
360 ah->txeol_interrupt_mask &= ~(1 << q);
361 ah->txurn_interrupt_mask &= ~(1 << q);
f1dc5600
S
362 ath9k_hw_set_txq_interrupts(ah, qi);
363
364 return true;
365}
7322fd19 366EXPORT_SYMBOL(ath9k_hw_releasetxqueue);
f1dc5600 367
cbe61d8a 368bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
f1dc5600 369{
c46917bb 370 struct ath_common *common = ath9k_hw_common(ah);
2660b81a 371 struct ath9k_channel *chan = ah->curchan;
f1dc5600
S
372 struct ath9k_tx_queue_info *qi;
373 u32 cwMin, chanCwMin, value;
374
2660b81a 375 qi = &ah->txq[q];
f1dc5600 376 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
d2182b69 377 ath_dbg(common, QUEUE, "Reset TXQ, inactive queue: %u\n", q);
f1dc5600
S
378 return true;
379 }
380
d2182b69 381 ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q);
f1dc5600
S
382
383 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
384 if (chan && IS_CHAN_B(chan))
385 chanCwMin = INIT_CWMIN_11B;
386 else
387 chanCwMin = INIT_CWMIN;
388
389 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
390 } else
391 cwMin = qi->tqi_cwmin;
392
7d0d0df0
S
393 ENABLE_REGWRITE_BUFFER(ah);
394
f1dc5600
S
395 REG_WRITE(ah, AR_DLCL_IFS(q),
396 SM(cwMin, AR_D_LCL_IFS_CWMIN) |
397 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
398 SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
399
400 REG_WRITE(ah, AR_DRETRY_LIMIT(q),
401 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
402 SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
403 SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
404
405 REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
94333f59
RM
406
407 if (AR_SREV_9340(ah))
408 REG_WRITE(ah, AR_DMISC(q),
409 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
410 else
411 REG_WRITE(ah, AR_DMISC(q),
412 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
f1dc5600
S
413
414 if (qi->tqi_cbrPeriod) {
415 REG_WRITE(ah, AR_QCBRCFG(q),
416 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
417 SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
ca7a4deb
FF
418 REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
419 (qi->tqi_cbrOverflowLimit ?
420 AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
f1dc5600
S
421 }
422 if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
423 REG_WRITE(ah, AR_QRDYTIMECFG(q),
424 SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
425 AR_Q_RDYTIMECFG_EN);
426 }
427
428 REG_WRITE(ah, AR_DCHNTIME(q),
429 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
430 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
431
432 if (qi->tqi_burstTime
ca7a4deb
FF
433 && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))
434 REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);
f1dc5600 435
ca7a4deb
FF
436 if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)
437 REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
7d0d0df0
S
438
439 REGWRITE_BUFFER_FLUSH(ah);
7d0d0df0 440
ca7a4deb
FF
441 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
442 REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);
443
f1dc5600
S
444 switch (qi->tqi_type) {
445 case ATH9K_TX_QUEUE_BEACON:
7d0d0df0
S
446 ENABLE_REGWRITE_BUFFER(ah);
447
ca7a4deb
FF
448 REG_SET_BIT(ah, AR_QMISC(q),
449 AR_Q_MISC_FSP_DBA_GATED
450 | AR_Q_MISC_BEACON_USE
451 | AR_Q_MISC_CBR_INCR_DIS1);
f1dc5600 452
ca7a4deb
FF
453 REG_SET_BIT(ah, AR_DMISC(q),
454 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
f1dc5600 455 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
ca7a4deb
FF
456 | AR_D_MISC_BEACON_USE
457 | AR_D_MISC_POST_FR_BKOFF_DIS);
7d0d0df0
S
458
459 REGWRITE_BUFFER_FLUSH(ah);
7d0d0df0 460
9a2af889
LR
461 /*
462 * cwmin and cwmax should be 0 for beacon queue
463 * but not for IBSS as we would create an imbalance
464 * on beaconing fairness for participating nodes.
465 */
466 if (AR_SREV_9300_20_OR_LATER(ah) &&
467 ah->opmode != NL80211_IFTYPE_ADHOC) {
3deb4da5
LR
468 REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)
469 | SM(0, AR_D_LCL_IFS_CWMAX)
470 | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
471 }
f1dc5600
S
472 break;
473 case ATH9K_TX_QUEUE_CAB:
7d0d0df0
S
474 ENABLE_REGWRITE_BUFFER(ah);
475
ca7a4deb
FF
476 REG_SET_BIT(ah, AR_QMISC(q),
477 AR_Q_MISC_FSP_DBA_GATED
478 | AR_Q_MISC_CBR_INCR_DIS1
479 | AR_Q_MISC_CBR_INCR_DIS0);
f1dc5600 480 value = (qi->tqi_readyTime -
2660b81a
S
481 (ah->config.sw_beacon_response_time -
482 ah->config.dma_beacon_response_time) -
483 ah->config.additional_swba_backoff) * 1024;
f1dc5600
S
484 REG_WRITE(ah, AR_QRDYTIMECFG(q),
485 value | AR_Q_RDYTIMECFG_EN);
ca7a4deb
FF
486 REG_SET_BIT(ah, AR_DMISC(q),
487 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
f1dc5600 488 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
7d0d0df0
S
489
490 REGWRITE_BUFFER_FLUSH(ah);
7d0d0df0 491
f1dc5600
S
492 break;
493 case ATH9K_TX_QUEUE_PSPOLL:
ca7a4deb 494 REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1);
f1dc5600
S
495 break;
496 case ATH9K_TX_QUEUE_UAPSD:
ca7a4deb 497 REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
f1dc5600
S
498 break;
499 default:
500 break;
501 }
502
503 if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
ca7a4deb
FF
504 REG_SET_BIT(ah, AR_DMISC(q),
505 SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
506 AR_D_MISC_ARB_LOCKOUT_CNTRL) |
507 AR_D_MISC_POST_FR_BKOFF_DIS);
f1dc5600
S
508 }
509
79de2375
LR
510 if (AR_SREV_9300_20_OR_LATER(ah))
511 REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
512
f1dc5600 513 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
2660b81a 514 ah->txok_interrupt_mask |= 1 << q;
f1dc5600 515 else
2660b81a 516 ah->txok_interrupt_mask &= ~(1 << q);
f1dc5600 517 if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
2660b81a 518 ah->txerr_interrupt_mask |= 1 << q;
f1dc5600 519 else
2660b81a 520 ah->txerr_interrupt_mask &= ~(1 << q);
f1dc5600 521 if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
2660b81a 522 ah->txdesc_interrupt_mask |= 1 << q;
f1dc5600 523 else
2660b81a 524 ah->txdesc_interrupt_mask &= ~(1 << q);
f1dc5600 525 if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
2660b81a 526 ah->txeol_interrupt_mask |= 1 << q;
f1dc5600 527 else
2660b81a 528 ah->txeol_interrupt_mask &= ~(1 << q);
f1dc5600 529 if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
2660b81a 530 ah->txurn_interrupt_mask |= 1 << q;
f1dc5600 531 else
2660b81a 532 ah->txurn_interrupt_mask &= ~(1 << q);
f1dc5600
S
533 ath9k_hw_set_txq_interrupts(ah, qi);
534
535 return true;
536}
7322fd19 537EXPORT_SYMBOL(ath9k_hw_resettxqueue);
f1dc5600 538
cbe61d8a 539int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
3de21116 540 struct ath_rx_status *rs)
f1dc5600
S
541{
542 struct ar5416_desc ads;
543 struct ar5416_desc *adsp = AR5416DESC(ds);
544 u32 phyerr;
545
546 if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
547 return -EINPROGRESS;
548
549 ads.u.rx = adsp->u.rx;
550
8e6f5aa2
FF
551 rs->rs_status = 0;
552 rs->rs_flags = 0;
f1dc5600 553
8e6f5aa2
FF
554 rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
555 rs->rs_tstamp = ads.AR_RcvTimestamp;
f1dc5600 556
dd8b15b0 557 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
8e6f5aa2
FF
558 rs->rs_rssi = ATH9K_RSSI_BAD;
559 rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
560 rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
561 rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
562 rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
563 rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
564 rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
dd8b15b0 565 } else {
8e6f5aa2
FF
566 rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
567 rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
dd8b15b0 568 AR_RxRSSIAnt00);
8e6f5aa2 569 rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
dd8b15b0 570 AR_RxRSSIAnt01);
8e6f5aa2 571 rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
dd8b15b0 572 AR_RxRSSIAnt02);
8e6f5aa2 573 rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
dd8b15b0 574 AR_RxRSSIAnt10);
8e6f5aa2 575 rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
dd8b15b0 576 AR_RxRSSIAnt11);
8e6f5aa2 577 rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
dd8b15b0
SB
578 AR_RxRSSIAnt12);
579 }
f1dc5600 580 if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
8e6f5aa2 581 rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
f1dc5600 582 else
8e6f5aa2 583 rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
f1dc5600 584
1b8714f7 585 rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
8e6f5aa2 586 rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
f1dc5600 587
8e6f5aa2
FF
588 rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
589 rs->rs_moreaggr =
f1dc5600 590 (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
8e6f5aa2
FF
591 rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
592 rs->rs_flags =
f1dc5600 593 (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
8e6f5aa2 594 rs->rs_flags |=
f1dc5600
S
595 (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
596
597 if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
8e6f5aa2 598 rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
f1dc5600 599 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
8e6f5aa2 600 rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
f1dc5600 601 if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
8e6f5aa2 602 rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
f1dc5600
S
603
604 if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
115dad7a
FF
605 /*
606 * Treat these errors as mutually exclusive to avoid spurious
607 * extra error reports from the hardware. If a CRC error is
608 * reported, then decryption and MIC errors are irrelevant,
609 * the frame is going to be dropped either way
610 */
f1dc5600 611 if (ads.ds_rxstatus8 & AR_CRCErr)
8e6f5aa2 612 rs->rs_status |= ATH9K_RXERR_CRC;
115dad7a 613 else if (ads.ds_rxstatus8 & AR_PHYErr) {
8e6f5aa2 614 rs->rs_status |= ATH9K_RXERR_PHY;
f1dc5600 615 phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
8e6f5aa2 616 rs->rs_phyerr = phyerr;
115dad7a 617 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
8e6f5aa2 618 rs->rs_status |= ATH9K_RXERR_DECRYPT;
115dad7a 619 else if (ads.ds_rxstatus8 & AR_MichaelErr)
8e6f5aa2 620 rs->rs_status |= ATH9K_RXERR_MIC;
f1dc5600
S
621 }
622
7a532fe7
FF
623 if (ads.ds_rxstatus8 & AR_KeyMiss)
624 rs->rs_status |= ATH9K_RXERR_KEYMISS;
625
f1dc5600
S
626 return 0;
627}
7322fd19 628EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
f1dc5600 629
e7824a50
LR
630/*
631 * This can stop or re-enables RX.
632 *
633 * If bool is set this will kill any frame which is currently being
634 * transferred between the MAC and baseband and also prevent any new
635 * frames from getting started.
636 */
cbe61d8a 637bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
f1dc5600
S
638{
639 u32 reg;
640
641 if (set) {
642 REG_SET_BIT(ah, AR_DIAG_SW,
643 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
644
0caa7b14
S
645 if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
646 0, AH_WAIT_TIMEOUT)) {
f1dc5600
S
647 REG_CLR_BIT(ah, AR_DIAG_SW,
648 (AR_DIAG_RX_DIS |
649 AR_DIAG_RX_ABORT));
650
651 reg = REG_READ(ah, AR_OBS_BUS_1);
3800276a
JP
652 ath_err(ath9k_hw_common(ah),
653 "RX failed to go idle in 10 ms RXSM=0x%x\n",
654 reg);
f1dc5600
S
655
656 return false;
657 }
658 } else {
659 REG_CLR_BIT(ah, AR_DIAG_SW,
660 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
661 }
662
663 return true;
664}
7322fd19 665EXPORT_SYMBOL(ath9k_hw_setrxabort);
f1dc5600 666
cbe61d8a 667void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
f1dc5600
S
668{
669 REG_WRITE(ah, AR_RXDP, rxdp);
670}
7322fd19 671EXPORT_SYMBOL(ath9k_hw_putrxbuf);
f1dc5600 672
40346b66 673void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning)
f1dc5600 674{
f1dc5600
S
675 ath9k_enable_mib_counters(ah);
676
40346b66 677 ath9k_ani_reset(ah, is_scanning);
e7594072 678
8aa15e15 679 REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
f1dc5600 680}
7322fd19 681EXPORT_SYMBOL(ath9k_hw_startpcureceive);
f1dc5600 682
9b9cc61c
VT
683void ath9k_hw_abortpcurecv(struct ath_hw *ah)
684{
685 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
686
687 ath9k_hw_disable_mib_counters(ah);
688}
689EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
690
5882da02 691bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
f1dc5600 692{
0caa7b14 693#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
c46917bb 694 struct ath_common *common = ath9k_hw_common(ah);
5882da02 695 u32 mac_status, last_mac_status = 0;
0caa7b14
S
696 int i;
697
5882da02
FF
698 /* Enable access to the DMA observation bus */
699 REG_WRITE(ah, AR_MACMISC,
700 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
701 (AR_MACMISC_MISC_OBS_BUS_1 <<
702 AR_MACMISC_MISC_OBS_BUS_MSB_S)));
703
f1dc5600
S
704 REG_WRITE(ah, AR_CR, AR_CR_RXD);
705
0caa7b14
S
706 /* Wait for rx enable bit to go low */
707 for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
708 if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
709 break;
5882da02
FF
710
711 if (!AR_SREV_9300_20_OR_LATER(ah)) {
712 mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
713 if (mac_status == 0x1c0 && mac_status == last_mac_status) {
714 *reset = true;
715 break;
716 }
717
718 last_mac_status = mac_status;
719 }
720
0caa7b14
S
721 udelay(AH_TIME_QUANTUM);
722 }
723
724 if (i == 0) {
3800276a 725 ath_err(common,
5882da02 726 "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
3800276a
JP
727 AH_RX_STOP_DMA_TIMEOUT / 1000,
728 REG_READ(ah, AR_CR),
5882da02
FF
729 REG_READ(ah, AR_DIAG_SW),
730 REG_READ(ah, AR_DMADBG_7));
f1dc5600
S
731 return false;
732 } else {
733 return true;
734 }
0caa7b14 735
0caa7b14 736#undef AH_RX_STOP_DMA_TIMEOUT
f1dc5600 737}
7322fd19 738EXPORT_SYMBOL(ath9k_hw_stopdmarecv);
536b3a7a
LR
739
740int ath9k_hw_beaconq_setup(struct ath_hw *ah)
741{
742 struct ath9k_tx_queue_info qi;
743
744 memset(&qi, 0, sizeof(qi));
745 qi.tqi_aifs = 1;
746 qi.tqi_cwmin = 0;
747 qi.tqi_cwmax = 0;
748 /* NB: don't enable any interrupts */
749 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
750}
751EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
55e82df4
VT
752
753bool ath9k_hw_intrpend(struct ath_hw *ah)
754{
755 u32 host_isr;
756
757 if (AR_SREV_9100(ah))
758 return true;
759
760 host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
e3584813
MSS
761
762 if (((host_isr & AR_INTR_MAC_IRQ) ||
763 (host_isr & AR_INTR_ASYNC_MASK_MCI)) &&
764 (host_isr != AR_INTR_SPURIOUS))
55e82df4
VT
765 return true;
766
767 host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
768 if ((host_isr & AR_INTR_SYNC_DEFAULT)
769 && (host_isr != AR_INTR_SPURIOUS))
770 return true;
771
772 return false;
773}
774EXPORT_SYMBOL(ath9k_hw_intrpend);
775
4df3071e
FF
776void ath9k_hw_disable_interrupts(struct ath_hw *ah)
777{
778 struct ath_common *common = ath9k_hw_common(ah);
779
e8fe7336
RM
780 if (!(ah->imask & ATH9K_INT_GLOBAL))
781 atomic_set(&ah->intr_ref_cnt, -1);
782 else
783 atomic_dec(&ah->intr_ref_cnt);
784
d2182b69 785 ath_dbg(common, INTERRUPT, "disable IER\n");
4df3071e
FF
786 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
787 (void) REG_READ(ah, AR_IER);
788 if (!AR_SREV_9100(ah)) {
789 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
790 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
791
792 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
793 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
794 }
795}
796EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
797
798void ath9k_hw_enable_interrupts(struct ath_hw *ah)
799{
800 struct ath_common *common = ath9k_hw_common(ah);
79d1d2b8 801 u32 sync_default = AR_INTR_SYNC_DEFAULT;
f229f815 802 u32 async_mask;
4df3071e
FF
803
804 if (!(ah->imask & ATH9K_INT_GLOBAL))
805 return;
806
e8fe7336 807 if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
d2182b69 808 ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
e8fe7336
RM
809 atomic_read(&ah->intr_ref_cnt));
810 return;
811 }
812
79d1d2b8
VT
813 if (AR_SREV_9340(ah))
814 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
815
f229f815
MSS
816 async_mask = AR_INTR_MAC_IRQ;
817
818 if (ah->imask & ATH9K_INT_MCI)
819 async_mask |= AR_INTR_ASYNC_MASK_MCI;
820
d2182b69 821 ath_dbg(common, INTERRUPT, "enable IER\n");
4df3071e
FF
822 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
823 if (!AR_SREV_9100(ah)) {
f229f815
MSS
824 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, async_mask);
825 REG_WRITE(ah, AR_INTR_ASYNC_MASK, async_mask);
4df3071e 826
79d1d2b8
VT
827 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
828 REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default);
4df3071e 829 }
d2182b69 830 ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
226afe68 831 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
4df3071e
FF
832}
833EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
834
72d874c6 835void ath9k_hw_set_interrupts(struct ath_hw *ah)
55e82df4 836{
72d874c6 837 enum ath9k_int ints = ah->imask;
55e82df4
VT
838 u32 mask, mask2;
839 struct ath9k_hw_capabilities *pCap = &ah->caps;
840 struct ath_common *common = ath9k_hw_common(ah);
841
4df3071e 842 if (!(ints & ATH9K_INT_GLOBAL))
385918cc 843 ath9k_hw_disable_interrupts(ah);
55e82df4 844
d2182b69 845 ath_dbg(common, INTERRUPT, "New interrupt mask 0x%x\n", ints);
55e82df4 846
55e82df4
VT
847 mask = ints & ATH9K_INT_COMMON;
848 mask2 = 0;
849
850 if (ints & ATH9K_INT_TX) {
851 if (ah->config.tx_intr_mitigation)
852 mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
5bea4006
LR
853 else {
854 if (ah->txok_interrupt_mask)
855 mask |= AR_IMR_TXOK;
856 if (ah->txdesc_interrupt_mask)
857 mask |= AR_IMR_TXDESC;
858 }
55e82df4
VT
859 if (ah->txerr_interrupt_mask)
860 mask |= AR_IMR_TXERR;
861 if (ah->txeol_interrupt_mask)
862 mask |= AR_IMR_TXEOL;
863 }
864 if (ints & ATH9K_INT_RX) {
865 if (AR_SREV_9300_20_OR_LATER(ah)) {
866 mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
867 if (ah->config.rx_intr_mitigation) {
868 mask &= ~AR_IMR_RXOK_LP;
869 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
870 } else {
871 mask |= AR_IMR_RXOK_LP;
872 }
873 } else {
874 if (ah->config.rx_intr_mitigation)
875 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
876 else
877 mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
878 }
879 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
880 mask |= AR_IMR_GENTMR;
881 }
882
f78eb657
VN
883 if (ints & ATH9K_INT_GENTIMER)
884 mask |= AR_IMR_GENTMR;
885
55e82df4
VT
886 if (ints & (ATH9K_INT_BMISC)) {
887 mask |= AR_IMR_BCNMISC;
888 if (ints & ATH9K_INT_TIM)
889 mask2 |= AR_IMR_S2_TIM;
890 if (ints & ATH9K_INT_DTIM)
891 mask2 |= AR_IMR_S2_DTIM;
892 if (ints & ATH9K_INT_DTIMSYNC)
893 mask2 |= AR_IMR_S2_DTIMSYNC;
894 if (ints & ATH9K_INT_CABEND)
895 mask2 |= AR_IMR_S2_CABEND;
896 if (ints & ATH9K_INT_TSFOOR)
897 mask2 |= AR_IMR_S2_TSFOOR;
898 }
899
900 if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
901 mask |= AR_IMR_BCNMISC;
902 if (ints & ATH9K_INT_GTT)
903 mask2 |= AR_IMR_S2_GTT;
904 if (ints & ATH9K_INT_CST)
905 mask2 |= AR_IMR_S2_CST;
906 }
907
d2182b69 908 ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask);
55e82df4
VT
909 REG_WRITE(ah, AR_IMR, mask);
910 ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
911 AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
912 AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
913 ah->imrs2_reg |= mask2;
914 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
915
916 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
917 if (ints & ATH9K_INT_TIM_TIMER)
918 REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
919 else
920 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
921 }
922
4df3071e 923 return;
55e82df4
VT
924}
925EXPORT_SYMBOL(ath9k_hw_set_interrupts);