mac.c 24.8 KB
Newer Older
S
Sujith 已提交
1
/*
2
 * Copyright (c) 2008-2009 Atheros Communications Inc.
S
Sujith 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

17
#include "hw.h"
18
#include "hw-ops.h"
S
Sujith 已提交
19

20 21 22
static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
					struct ath9k_tx_queue_info *qi)
{
J
Joe Perches 已提交
23 24 25 26 27
	ath_dbg(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
		"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
		ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
		ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
		ah->txurn_interrupt_mask);
28

S
Sujith 已提交
29 30
	ENABLE_REGWRITE_BUFFER(ah);

31 32 33 34 35 36 37 38 39 40
	REG_WRITE(ah, AR_IMR_S0,
		  SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
		  | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
	REG_WRITE(ah, AR_IMR_S1,
		  SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
		  | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));

	ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
	ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
S
Sujith 已提交
41 42

	REGWRITE_BUFFER_FLUSH(ah);
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
}

u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
{
	return REG_READ(ah, AR_QTXDP(q));
}
EXPORT_SYMBOL(ath9k_hw_gettxbuf);

void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
{
	REG_WRITE(ah, AR_QTXDP(q), txdp);
}
EXPORT_SYMBOL(ath9k_hw_puttxbuf);

void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
{
J
Joe Perches 已提交
59 60
	ath_dbg(ath9k_hw_common(ah), ATH_DBG_QUEUE,
		"Enable TXE on queue: %u\n", q);
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	REG_WRITE(ah, AR_Q_TXE, 1 << q);
}
EXPORT_SYMBOL(ath9k_hw_txstart);

void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
{
	struct ar5416_desc *ads = AR5416DESC(ds);

	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
}
EXPORT_SYMBOL(ath9k_hw_cleartxdesc);

u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
{
	u32 npend;

	npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
	if (npend == 0) {

		if (REG_READ(ah, AR_Q_TXE) & (1 << q))
			npend = 1;
	}

	return npend;
}
EXPORT_SYMBOL(ath9k_hw_numtxpending);

/**
 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
 *
 * @ah: atheros hardware struct
 * @bIncTrigLevel: whether or not the frame trigger level should be updated
 *
 * The frame trigger level specifies the minimum number of bytes,
 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
 * before the PCU will initiate sending the frame on the air. This can
 * mean we initiate transmit before a full frame is on the PCU TX FIFO.
 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
 * first)
 *
 * Caution must be taken to ensure to set the frame trigger level based
 * on the DMA request size. For example if the DMA request size is set to
 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
 * there need to be enough space in the tx FIFO for the requested transfer
 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
 * the threshold to a value beyond 6, then the transmit will hang.
 *
 * Current dual   stream devices have a PCU TX FIFO size of 8 KB.
 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
 * there is a hardware issue which forces us to use 2 KB instead so the
 * frame trigger level must not exceed 2 KB for these chipsets.
 */
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
{
	u32 txcfg, curLevel, newLevel;

	if (ah->tx_trig_level >= ah->config.max_txtrig_level)
		return false;

124
	ath9k_hw_disable_interrupts(ah);
125 126 127 128 129 130 131 132 133 134 135 136 137

	txcfg = REG_READ(ah, AR_TXCFG);
	curLevel = MS(txcfg, AR_FTRIG);
	newLevel = curLevel;
	if (bIncTrigLevel) {
		if (curLevel < ah->config.max_txtrig_level)
			newLevel++;
	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
		newLevel--;
	if (newLevel != curLevel)
		REG_WRITE(ah, AR_TXCFG,
			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));

138
	ath9k_hw_enable_interrupts(ah);
139 140 141 142 143 144 145

	ah->tx_trig_level = newLevel;

	return newLevel != curLevel;
}
EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);

146
void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
147
{
148
	int i, q;
149

150
	REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
151

152 153 154
	REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
	REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
155

156 157 158 159
	for (q = 0; q < AR_NUM_QCU; q++) {
		for (i = 0; i < 1000; i++) {
			if (i)
				udelay(5);
160

161
			if (!ath9k_hw_numtxpending(ah, q))
162 163
				break;
		}
164
	}
165

166 167 168
	REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
	REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
	REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
169

170 171 172
	REG_WRITE(ah, AR_Q_TXD, 0);
}
EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
173

174
bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
175
{
176
#define ATH9K_TX_STOP_DMA_TIMEOUT	1000    /* usec */
177
#define ATH9K_TIME_QUANTUM		100     /* usec */
178 179
	int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
	int wait;
180 181 182 183

	REG_WRITE(ah, AR_Q_TXD, 1 << q);

	for (wait = wait_time; wait != 0; wait--) {
184
		if (wait != wait_time)
185 186
			udelay(ATH9K_TIME_QUANTUM);

187 188
		if (ath9k_hw_numtxpending(ah, q) == 0)
			break;
189 190 191
	}

	REG_WRITE(ah, AR_Q_TXD, 0);
192

193 194 195 196 197
	return wait != 0;

#undef ATH9K_TX_STOP_DMA_TIMEOUT
#undef ATH9K_TIME_QUANTUM
}
198
EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
199

200
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
S
Sujith 已提交
201
{
202 203
	*txqs &= ah->intr_txqs;
	ah->intr_txqs &= ~(*txqs);
S
Sujith 已提交
204
}
205
EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs);
S
Sujith 已提交
206

207
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
S
Sujith 已提交
208 209 210
			    const struct ath9k_tx_queue_info *qinfo)
{
	u32 cw;
211
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
212 213
	struct ath9k_tx_queue_info *qi;

214
	qi = &ah->txq[q];
S
Sujith 已提交
215
	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
J
Joe Perches 已提交
216 217
		ath_dbg(common, ATH_DBG_QUEUE,
			"Set TXQ properties, inactive queue: %u\n", q);
S
Sujith 已提交
218 219 220
		return false;
	}

J
Joe Perches 已提交
221
	ath_dbg(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
S
Sujith 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269

	qi->tqi_ver = qinfo->tqi_ver;
	qi->tqi_subtype = qinfo->tqi_subtype;
	qi->tqi_qflags = qinfo->tqi_qflags;
	qi->tqi_priority = qinfo->tqi_priority;
	if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
		qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
	else
		qi->tqi_aifs = INIT_AIFS;
	if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
		cw = min(qinfo->tqi_cwmin, 1024U);
		qi->tqi_cwmin = 1;
		while (qi->tqi_cwmin < cw)
			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
	} else
		qi->tqi_cwmin = qinfo->tqi_cwmin;
	if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
		cw = min(qinfo->tqi_cwmax, 1024U);
		qi->tqi_cwmax = 1;
		while (qi->tqi_cwmax < cw)
			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
	} else
		qi->tqi_cwmax = INIT_CWMAX;

	if (qinfo->tqi_shretry != 0)
		qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
	else
		qi->tqi_shretry = INIT_SH_RETRY;
	if (qinfo->tqi_lgretry != 0)
		qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
	else
		qi->tqi_lgretry = INIT_LG_RETRY;
	qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
	qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
	qi->tqi_burstTime = qinfo->tqi_burstTime;
	qi->tqi_readyTime = qinfo->tqi_readyTime;

	switch (qinfo->tqi_subtype) {
	case ATH9K_WME_UPSD:
		if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
			qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
		break;
	default:
		break;
	}

	return true;
}
270
EXPORT_SYMBOL(ath9k_hw_set_txq_props);
S
Sujith 已提交
271

272
bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
S
Sujith 已提交
273 274
			    struct ath9k_tx_queue_info *qinfo)
{
275
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
276 277
	struct ath9k_tx_queue_info *qi;

278
	qi = &ah->txq[q];
S
Sujith 已提交
279
	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
J
Joe Perches 已提交
280 281
		ath_dbg(common, ATH_DBG_QUEUE,
			"Get TXQ properties, inactive queue: %u\n", q);
S
Sujith 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
		return false;
	}

	qinfo->tqi_qflags = qi->tqi_qflags;
	qinfo->tqi_ver = qi->tqi_ver;
	qinfo->tqi_subtype = qi->tqi_subtype;
	qinfo->tqi_qflags = qi->tqi_qflags;
	qinfo->tqi_priority = qi->tqi_priority;
	qinfo->tqi_aifs = qi->tqi_aifs;
	qinfo->tqi_cwmin = qi->tqi_cwmin;
	qinfo->tqi_cwmax = qi->tqi_cwmax;
	qinfo->tqi_shretry = qi->tqi_shretry;
	qinfo->tqi_lgretry = qi->tqi_lgretry;
	qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
	qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
	qinfo->tqi_burstTime = qi->tqi_burstTime;
	qinfo->tqi_readyTime = qi->tqi_readyTime;

	return true;
}
302
EXPORT_SYMBOL(ath9k_hw_get_txq_props);
S
Sujith 已提交
303

304
int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
S
Sujith 已提交
305 306
			  const struct ath9k_tx_queue_info *qinfo)
{
307
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
308 309 310 311 312
	struct ath9k_tx_queue_info *qi;
	int q;

	switch (type) {
	case ATH9K_TX_QUEUE_BEACON:
313
		q = ATH9K_NUM_TX_QUEUES - 1;
S
Sujith 已提交
314 315
		break;
	case ATH9K_TX_QUEUE_CAB:
316
		q = ATH9K_NUM_TX_QUEUES - 2;
S
Sujith 已提交
317 318 319 320 321
		break;
	case ATH9K_TX_QUEUE_PSPOLL:
		q = 1;
		break;
	case ATH9K_TX_QUEUE_UAPSD:
322
		q = ATH9K_NUM_TX_QUEUES - 3;
S
Sujith 已提交
323 324
		break;
	case ATH9K_TX_QUEUE_DATA:
325
		for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
326
			if (ah->txq[q].tqi_type ==
S
Sujith 已提交
327 328
			    ATH9K_TX_QUEUE_INACTIVE)
				break;
329
		if (q == ATH9K_NUM_TX_QUEUES) {
330
			ath_err(common, "No available TX queue\n");
S
Sujith 已提交
331 332 333 334
			return -1;
		}
		break;
	default:
335
		ath_err(common, "Invalid TX queue type: %u\n", type);
S
Sujith 已提交
336 337 338
		return -1;
	}

J
Joe Perches 已提交
339
	ath_dbg(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
S
Sujith 已提交
340

341
	qi = &ah->txq[q];
S
Sujith 已提交
342
	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
343
		ath_err(common, "TX queue: %u already active\n", q);
S
Sujith 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
		return -1;
	}
	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
	qi->tqi_type = type;
	if (qinfo == NULL) {
		qi->tqi_qflags =
			TXQ_FLAG_TXOKINT_ENABLE
			| TXQ_FLAG_TXERRINT_ENABLE
			| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
		qi->tqi_aifs = INIT_AIFS;
		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
		qi->tqi_cwmax = INIT_CWMAX;
		qi->tqi_shretry = INIT_SH_RETRY;
		qi->tqi_lgretry = INIT_LG_RETRY;
		qi->tqi_physCompBuf = 0;
	} else {
		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
		(void) ath9k_hw_set_txq_props(ah, q, qinfo);
	}

	return q;
}
366
EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
S
Sujith 已提交
367

368
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
S
Sujith 已提交
369
{
370
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
371 372
	struct ath9k_tx_queue_info *qi;

373
	qi = &ah->txq[q];
S
Sujith 已提交
374
	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
J
Joe Perches 已提交
375 376
		ath_dbg(common, ATH_DBG_QUEUE,
			"Release TXQ, inactive queue: %u\n", q);
S
Sujith 已提交
377 378 379
		return false;
	}

J
Joe Perches 已提交
380
	ath_dbg(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
S
Sujith 已提交
381 382

	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
383 384 385 386 387
	ah->txok_interrupt_mask &= ~(1 << q);
	ah->txerr_interrupt_mask &= ~(1 << q);
	ah->txdesc_interrupt_mask &= ~(1 << q);
	ah->txeol_interrupt_mask &= ~(1 << q);
	ah->txurn_interrupt_mask &= ~(1 << q);
S
Sujith 已提交
388 389 390 391
	ath9k_hw_set_txq_interrupts(ah, qi);

	return true;
}
392
EXPORT_SYMBOL(ath9k_hw_releasetxqueue);
S
Sujith 已提交
393

394
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
S
Sujith 已提交
395
{
396
	struct ath_common *common = ath9k_hw_common(ah);
397
	struct ath9k_channel *chan = ah->curchan;
S
Sujith 已提交
398 399 400
	struct ath9k_tx_queue_info *qi;
	u32 cwMin, chanCwMin, value;

401
	qi = &ah->txq[q];
S
Sujith 已提交
402
	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
J
Joe Perches 已提交
403 404
		ath_dbg(common, ATH_DBG_QUEUE,
			"Reset TXQ, inactive queue: %u\n", q);
S
Sujith 已提交
405 406 407
		return true;
	}

J
Joe Perches 已提交
408
	ath_dbg(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
S
Sujith 已提交
409 410 411 412 413 414 415 416 417 418 419

	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
		if (chan && IS_CHAN_B(chan))
			chanCwMin = INIT_CWMIN_11B;
		else
			chanCwMin = INIT_CWMIN;

		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
	} else
		cwMin = qi->tqi_cwmin;

S
Sujith 已提交
420 421
	ENABLE_REGWRITE_BUFFER(ah);

S
Sujith 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
	REG_WRITE(ah, AR_DLCL_IFS(q),
		  SM(cwMin, AR_D_LCL_IFS_CWMIN) |
		  SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
		  SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));

	REG_WRITE(ah, AR_DRETRY_LIMIT(q),
		  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
		  SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
		  SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));

	REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
	REG_WRITE(ah, AR_DMISC(q),
		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);

	if (qi->tqi_cbrPeriod) {
		REG_WRITE(ah, AR_QCBRCFG(q),
			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
			  SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
440 441 442
		REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
			    (qi->tqi_cbrOverflowLimit ?
			     AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
S
Sujith 已提交
443 444 445 446 447 448 449 450 451 452 453 454
	}
	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
		REG_WRITE(ah, AR_QRDYTIMECFG(q),
			  SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
			  AR_Q_RDYTIMECFG_EN);
	}

	REG_WRITE(ah, AR_DCHNTIME(q),
		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));

	if (qi->tqi_burstTime
455 456
	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))
		REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);
S
Sujith 已提交
457

458 459
	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)
		REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
S
Sujith 已提交
460 461 462

	REGWRITE_BUFFER_FLUSH(ah);

463 464 465
	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
		REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);

S
Sujith 已提交
466 467
	switch (qi->tqi_type) {
	case ATH9K_TX_QUEUE_BEACON:
S
Sujith 已提交
468 469
		ENABLE_REGWRITE_BUFFER(ah);

470 471 472 473
		REG_SET_BIT(ah, AR_QMISC(q),
			    AR_Q_MISC_FSP_DBA_GATED
			    | AR_Q_MISC_BEACON_USE
			    | AR_Q_MISC_CBR_INCR_DIS1);
S
Sujith 已提交
474

475 476
		REG_SET_BIT(ah, AR_DMISC(q),
			    (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
S
Sujith 已提交
477
			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
478 479
			    | AR_D_MISC_BEACON_USE
			    | AR_D_MISC_POST_FR_BKOFF_DIS);
S
Sujith 已提交
480 481 482

		REGWRITE_BUFFER_FLUSH(ah);

483 484 485 486 487 488 489
		/*
		 * cwmin and cwmax should be 0 for beacon queue
		 * but not for IBSS as we would create an imbalance
		 * on beaconing fairness for participating nodes.
		 */
		if (AR_SREV_9300_20_OR_LATER(ah) &&
		    ah->opmode != NL80211_IFTYPE_ADHOC) {
490 491 492 493
			REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)
				  | SM(0, AR_D_LCL_IFS_CWMAX)
				  | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
		}
S
Sujith 已提交
494 495
		break;
	case ATH9K_TX_QUEUE_CAB:
S
Sujith 已提交
496 497
		ENABLE_REGWRITE_BUFFER(ah);

498 499 500 501
		REG_SET_BIT(ah, AR_QMISC(q),
			    AR_Q_MISC_FSP_DBA_GATED
			    | AR_Q_MISC_CBR_INCR_DIS1
			    | AR_Q_MISC_CBR_INCR_DIS0);
S
Sujith 已提交
502
		value = (qi->tqi_readyTime -
503 504 505
			 (ah->config.sw_beacon_response_time -
			  ah->config.dma_beacon_response_time) -
			 ah->config.additional_swba_backoff) * 1024;
S
Sujith 已提交
506 507
		REG_WRITE(ah, AR_QRDYTIMECFG(q),
			  value | AR_Q_RDYTIMECFG_EN);
508 509
		REG_SET_BIT(ah, AR_DMISC(q),
			    (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
S
Sujith 已提交
510
			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
S
Sujith 已提交
511 512 513

		REGWRITE_BUFFER_FLUSH(ah);

S
Sujith 已提交
514 515
		break;
	case ATH9K_TX_QUEUE_PSPOLL:
516
		REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1);
S
Sujith 已提交
517 518
		break;
	case ATH9K_TX_QUEUE_UAPSD:
519
		REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
S
Sujith 已提交
520 521 522 523 524 525
		break;
	default:
		break;
	}

	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
526 527 528 529
		REG_SET_BIT(ah, AR_DMISC(q),
			    SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
			       AR_D_MISC_ARB_LOCKOUT_CNTRL) |
			    AR_D_MISC_POST_FR_BKOFF_DIS);
S
Sujith 已提交
530 531
	}

532 533 534
	if (AR_SREV_9300_20_OR_LATER(ah))
		REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);

S
Sujith 已提交
535
	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
536
		ah->txok_interrupt_mask |= 1 << q;
S
Sujith 已提交
537
	else
538
		ah->txok_interrupt_mask &= ~(1 << q);
S
Sujith 已提交
539
	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
540
		ah->txerr_interrupt_mask |= 1 << q;
S
Sujith 已提交
541
	else
542
		ah->txerr_interrupt_mask &= ~(1 << q);
S
Sujith 已提交
543
	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
544
		ah->txdesc_interrupt_mask |= 1 << q;
S
Sujith 已提交
545
	else
546
		ah->txdesc_interrupt_mask &= ~(1 << q);
S
Sujith 已提交
547
	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
548
		ah->txeol_interrupt_mask |= 1 << q;
S
Sujith 已提交
549
	else
550
		ah->txeol_interrupt_mask &= ~(1 << q);
S
Sujith 已提交
551
	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
552
		ah->txurn_interrupt_mask |= 1 << q;
S
Sujith 已提交
553
	else
554
		ah->txurn_interrupt_mask &= ~(1 << q);
S
Sujith 已提交
555 556 557 558
	ath9k_hw_set_txq_interrupts(ah, qi);

	return true;
}
559
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
S
Sujith 已提交
560

561
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
562
			struct ath_rx_status *rs, u64 tsf)
S
Sujith 已提交
563 564 565 566 567 568 569 570 571 572
{
	struct ar5416_desc ads;
	struct ar5416_desc *adsp = AR5416DESC(ds);
	u32 phyerr;

	if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
		return -EINPROGRESS;

	ads.u.rx = adsp->u.rx;

573 574
	rs->rs_status = 0;
	rs->rs_flags = 0;
S
Sujith 已提交
575

576 577
	rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
	rs->rs_tstamp = ads.AR_RcvTimestamp;
S
Sujith 已提交
578

579
	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
580 581 582 583 584 585 586
		rs->rs_rssi = ATH9K_RSSI_BAD;
		rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
		rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
		rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
		rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
		rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
		rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
587
	} else {
588 589
		rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
		rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
590
						AR_RxRSSIAnt00);
591
		rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
592
						AR_RxRSSIAnt01);
593
		rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
594
						AR_RxRSSIAnt02);
595
		rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
596
						AR_RxRSSIAnt10);
597
		rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
598
						AR_RxRSSIAnt11);
599
		rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
600 601
						AR_RxRSSIAnt12);
	}
S
Sujith 已提交
602
	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
603
		rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
S
Sujith 已提交
604
	else
605
		rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
S
Sujith 已提交
606

607 608
	rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
	rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
S
Sujith 已提交
609

610 611
	rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
	rs->rs_moreaggr =
S
Sujith 已提交
612
		(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
613 614
	rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
	rs->rs_flags =
S
Sujith 已提交
615
		(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
616
	rs->rs_flags |=
S
Sujith 已提交
617 618 619
		(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;

	if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
620
		rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
S
Sujith 已提交
621
	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
622
		rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
S
Sujith 已提交
623
	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
624
		rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
S
Sujith 已提交
625 626

	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
627 628 629 630 631 632
		/*
		 * Treat these errors as mutually exclusive to avoid spurious
		 * extra error reports from the hardware. If a CRC error is
		 * reported, then decryption and MIC errors are irrelevant,
		 * the frame is going to be dropped either way
		 */
S
Sujith 已提交
633
		if (ads.ds_rxstatus8 & AR_CRCErr)
634
			rs->rs_status |= ATH9K_RXERR_CRC;
635
		else if (ads.ds_rxstatus8 & AR_PHYErr) {
636
			rs->rs_status |= ATH9K_RXERR_PHY;
S
Sujith 已提交
637
			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
638
			rs->rs_phyerr = phyerr;
639
		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
640
			rs->rs_status |= ATH9K_RXERR_DECRYPT;
641
		else if (ads.ds_rxstatus8 & AR_MichaelErr)
642
			rs->rs_status |= ATH9K_RXERR_MIC;
643

644
		if (ads.ds_rxstatus8 & AR_KeyMiss)
F
Felix Fietkau 已提交
645
			rs->rs_status |= ATH9K_RXERR_DECRYPT;
S
Sujith 已提交
646 647 648 649
	}

	return 0;
}
650
EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
S
Sujith 已提交
651

652 653 654 655 656 657 658
/*
 * This can stop or re-enables RX.
 *
 * If bool is set this will kill any frame which is currently being
 * transferred between the MAC and baseband and also prevent any new
 * frames from getting started.
 */
659
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
S
Sujith 已提交
660 661 662 663 664 665 666
{
	u32 reg;

	if (set) {
		REG_SET_BIT(ah, AR_DIAG_SW,
			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));

S
Sujith 已提交
667 668
		if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
				   0, AH_WAIT_TIMEOUT)) {
S
Sujith 已提交
669 670 671 672 673
			REG_CLR_BIT(ah, AR_DIAG_SW,
				    (AR_DIAG_RX_DIS |
				     AR_DIAG_RX_ABORT));

			reg = REG_READ(ah, AR_OBS_BUS_1);
674 675 676
			ath_err(ath9k_hw_common(ah),
				"RX failed to go idle in 10 ms RXSM=0x%x\n",
				reg);
S
Sujith 已提交
677 678 679 680 681 682 683 684 685 686

			return false;
		}
	} else {
		REG_CLR_BIT(ah, AR_DIAG_SW,
			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
	}

	return true;
}
687
EXPORT_SYMBOL(ath9k_hw_setrxabort);
S
Sujith 已提交
688

689
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
S
Sujith 已提交
690 691 692
{
	REG_WRITE(ah, AR_RXDP, rxdp);
}
693
EXPORT_SYMBOL(ath9k_hw_putrxbuf);
S
Sujith 已提交
694

695
void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning)
S
Sujith 已提交
696 697 698
{
	ath9k_enable_mib_counters(ah);

699
	ath9k_ani_reset(ah, is_scanning);
700

701
	REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
S
Sujith 已提交
702
}
703
EXPORT_SYMBOL(ath9k_hw_startpcureceive);
S
Sujith 已提交
704

705 706 707 708 709 710 711 712
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
{
	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);

	ath9k_hw_disable_mib_counters(ah);
}
EXPORT_SYMBOL(ath9k_hw_abortpcurecv);

713
bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
S
Sujith 已提交
714
{
S
Sujith 已提交
715
#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
716
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
717 718
	int i;

S
Sujith 已提交
719 720
	REG_WRITE(ah, AR_CR, AR_CR_RXD);

S
Sujith 已提交
721 722 723 724 725 726 727 728
	/* Wait for rx enable bit to go low */
	for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
		if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
			break;
		udelay(AH_TIME_QUANTUM);
	}

	if (i == 0) {
729 730 731 732 733
		ath_err(common,
			"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
			AH_RX_STOP_DMA_TIMEOUT / 1000,
			REG_READ(ah, AR_CR),
			REG_READ(ah, AR_DIAG_SW));
S
Sujith 已提交
734 735 736 737
		return false;
	} else {
		return true;
	}
S
Sujith 已提交
738 739

#undef AH_RX_STOP_DMA_TIMEOUT
S
Sujith 已提交
740
}
741
EXPORT_SYMBOL(ath9k_hw_stopdmarecv);
742 743 744 745 746 747 748 749 750 751 752 753 754

int ath9k_hw_beaconq_setup(struct ath_hw *ah)
{
	struct ath9k_tx_queue_info qi;

	memset(&qi, 0, sizeof(qi));
	qi.tqi_aifs = 1;
	qi.tqi_cwmin = 0;
	qi.tqi_cwmax = 0;
	/* NB: don't enable any interrupts */
	return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
}
EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775

bool ath9k_hw_intrpend(struct ath_hw *ah)
{
	u32 host_isr;

	if (AR_SREV_9100(ah))
		return true;

	host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
	if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
		return true;

	host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
	if ((host_isr & AR_INTR_SYNC_DEFAULT)
	    && (host_isr != AR_INTR_SPURIOUS))
		return true;

	return false;
}
EXPORT_SYMBOL(ath9k_hw_intrpend);

776 777 778 779
void ath9k_hw_disable_interrupts(struct ath_hw *ah)
{
	struct ath_common *common = ath9k_hw_common(ah);

J
Joe Perches 已提交
780
	ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
	REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
	(void) REG_READ(ah, AR_IER);
	if (!AR_SREV_9100(ah)) {
		REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
		(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);

		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
		(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
	}
}
EXPORT_SYMBOL(ath9k_hw_disable_interrupts);

void ath9k_hw_enable_interrupts(struct ath_hw *ah)
{
	struct ath_common *common = ath9k_hw_common(ah);

	if (!(ah->imask & ATH9K_INT_GLOBAL))
		return;

J
Joe Perches 已提交
800
	ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n");
801 802 803 804 805 806 807 808 809 810 811 812
	REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
	if (!AR_SREV_9100(ah)) {
		REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
			  AR_INTR_MAC_IRQ);
		REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);


		REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
			  AR_INTR_SYNC_DEFAULT);
		REG_WRITE(ah, AR_INTR_SYNC_MASK,
			  AR_INTR_SYNC_DEFAULT);
	}
J
Joe Perches 已提交
813 814
	ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
		REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
815 816 817 818
}
EXPORT_SYMBOL(ath9k_hw_enable_interrupts);

void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
819 820 821 822 823 824
{
	enum ath9k_int omask = ah->imask;
	u32 mask, mask2;
	struct ath9k_hw_capabilities *pCap = &ah->caps;
	struct ath_common *common = ath9k_hw_common(ah);

825
	if (!(ints & ATH9K_INT_GLOBAL))
826
		ath9k_hw_disable_interrupts(ah);
827

J
Joe Perches 已提交
828
	ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
829 830 831 832 833 834 835 836

	/* TODO: global int Ref count */
	mask = ints & ATH9K_INT_COMMON;
	mask2 = 0;

	if (ints & ATH9K_INT_TX) {
		if (ah->config.tx_intr_mitigation)
			mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
837 838 839 840 841 842
		else {
			if (ah->txok_interrupt_mask)
				mask |= AR_IMR_TXOK;
			if (ah->txdesc_interrupt_mask)
				mask |= AR_IMR_TXDESC;
		}
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
		if (ah->txerr_interrupt_mask)
			mask |= AR_IMR_TXERR;
		if (ah->txeol_interrupt_mask)
			mask |= AR_IMR_TXEOL;
	}
	if (ints & ATH9K_INT_RX) {
		if (AR_SREV_9300_20_OR_LATER(ah)) {
			mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
			if (ah->config.rx_intr_mitigation) {
				mask &= ~AR_IMR_RXOK_LP;
				mask |=  AR_IMR_RXMINTR | AR_IMR_RXINTM;
			} else {
				mask |= AR_IMR_RXOK_LP;
			}
		} else {
			if (ah->config.rx_intr_mitigation)
				mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
			else
				mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
		}
		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
			mask |= AR_IMR_GENTMR;
	}

	if (ints & (ATH9K_INT_BMISC)) {
		mask |= AR_IMR_BCNMISC;
		if (ints & ATH9K_INT_TIM)
			mask2 |= AR_IMR_S2_TIM;
		if (ints & ATH9K_INT_DTIM)
			mask2 |= AR_IMR_S2_DTIM;
		if (ints & ATH9K_INT_DTIMSYNC)
			mask2 |= AR_IMR_S2_DTIMSYNC;
		if (ints & ATH9K_INT_CABEND)
			mask2 |= AR_IMR_S2_CABEND;
		if (ints & ATH9K_INT_TSFOOR)
			mask2 |= AR_IMR_S2_TSFOOR;
	}

	if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
		mask |= AR_IMR_BCNMISC;
		if (ints & ATH9K_INT_GTT)
			mask2 |= AR_IMR_S2_GTT;
		if (ints & ATH9K_INT_CST)
			mask2 |= AR_IMR_S2_CST;
	}

J
Joe Perches 已提交
889
	ath_dbg(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
890 891 892 893 894 895 896 897 898 899 900 901 902 903
	REG_WRITE(ah, AR_IMR, mask);
	ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
			   AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
			   AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
	ah->imrs2_reg |= mask2;
	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);

	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
		if (ints & ATH9K_INT_TIM_TIMER)
			REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
		else
			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
	}

904 905
	if (ints & ATH9K_INT_GLOBAL)
		ath9k_hw_enable_interrupts(ah);
906

907
	return;
908 909
}
EXPORT_SYMBOL(ath9k_hw_set_interrupts);