1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * Copyright (c) 2008 Atheros Communications Inc.
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include <sys/ddi.h>
23
24 #include "arn_core.h"
25 #include "arn_hw.h"
26 #include "arn_reg.h"
27 #include "arn_phy.h"
28
29 /* ARGSUSED */
30 static void
ath9k_hw_set_txq_interrupts(struct ath_hal * ah,struct ath9k_tx_queue_info * qi)31 ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
32 struct ath9k_tx_queue_info *qi)
33 {
34 struct ath_hal_5416 *ahp = AH5416(ah);
35
36 ARN_DBG((ARN_DBG_INTERRUPT,
37 "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
38 __func__, ahp->ah_txOkInterruptMask,
39 ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask,
40 ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask));
41
42 REG_WRITE(ah, AR_IMR_S0,
43 SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) |
44 SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
45 REG_WRITE(ah, AR_IMR_S1,
46 SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)|
47 SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
48 REG_RMW_FIELD(ah, AR_IMR_S2,
49 AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
50 }
51
52 void
ath9k_hw_dmaRegDump(struct ath_hal * ah)53 ath9k_hw_dmaRegDump(struct ath_hal *ah)
54 {
55 uint32_t val[ATH9K_NUM_DMA_DEBUG_REGS];
56 int qcuOffset = 0, dcuOffset = 0;
57 uint32_t *qcuBase = &val[0], *dcuBase = &val[4];
58 int i;
59
60 REG_WRITE(ah, AR_MACMISC,
61 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
62 (AR_MACMISC_MISC_OBS_BUS_1 <<
63 AR_MACMISC_MISC_OBS_BUS_MSB_S)));
64
65 ARN_DBG((ARN_DBG_REG_IO, "Raw DMA Debug values:\n"));
66
67 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
68 if (i % 4 == 0)
69 ARN_DBG((ARN_DBG_REG_IO, "\n"));
70
71 val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof (uint32_t)));
72 ARN_DBG((ARN_DBG_REG_IO, "%d: %08x ", i, val[i]));
73 }
74
75 ARN_DBG((ARN_DBG_REG_IO, "\n\n"));
76 ARN_DBG((ARN_DBG_REG_IO,
77 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"));
78
79 for (i = 0; i < ATH9K_NUM_QUEUES;
80 i++, qcuOffset += 4, dcuOffset += 5) {
81 if (i == 8) {
82 qcuOffset = 0;
83 qcuBase++;
84 }
85
86 if (i == 6) {
87 dcuOffset = 0;
88 dcuBase++;
89 }
90
91 ARN_DBG((ARN_DBG_REG_IO,
92 "%2d %2x %1x %2x %2x\n",
93 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
94 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
95 val[2] & (0x7 << (i * 3)) >> (i * 3),
96 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset));
97 }
98
99 ARN_DBG((ARN_DBG_REG_IO, "\n"));
100 ARN_DBG((ARN_DBG_REG_IO,
101 "qcu_stitch state: %2x qcu_fetch state: %2x\n",
102 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22));
103 ARN_DBG((ARN_DBG_REG_IO,
104 "qcu_complete state: %2x dcu_complete state: %2x\n",
105 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)));
106 ARN_DBG((ARN_DBG_REG_IO,
107 "dcu_arb state: %2x dcu_fp state: %2x\n",
108 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27));
109 ARN_DBG((ARN_DBG_REG_IO,
110 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
111 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10));
112 ARN_DBG((ARN_DBG_REG_IO,
113 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
114 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12));
115 ARN_DBG((ARN_DBG_REG_IO,
116 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
117 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17));
118
119 ARN_DBG((ARN_DBG_REG_IO, "pcu observe 0x%x \n",
120 REG_READ(ah, AR_OBS_BUS_1)));
121 ARN_DBG((ARN_DBG_REG_IO,
122 "AR_CR 0x%x \n", REG_READ(ah, AR_CR)));
123 }
124
125 uint32_t
ath9k_hw_gettxbuf(struct ath_hal * ah,uint32_t q)126 ath9k_hw_gettxbuf(struct ath_hal *ah, uint32_t q)
127 {
128 return (REG_READ(ah, AR_QTXDP(q)));
129 }
130
131 boolean_t
ath9k_hw_puttxbuf(struct ath_hal * ah,uint32_t q,uint32_t txdp)132 ath9k_hw_puttxbuf(struct ath_hal *ah, uint32_t q, uint32_t txdp)
133 {
134 REG_WRITE(ah, AR_QTXDP(q), txdp);
135
136 return (B_TRUE);
137 }
138
139 boolean_t
ath9k_hw_txstart(struct ath_hal * ah,uint32_t q)140 ath9k_hw_txstart(struct ath_hal *ah, uint32_t q)
141 {
142 ARN_DBG((ARN_DBG_XMIT, "arn: ath9k_hw_txstart(): "
143 "tramist queue is %u\n", q));
144
145 REG_WRITE(ah, AR_Q_TXE, 1 << q);
146
147 return (B_TRUE);
148 }
149
150 uint32_t
ath9k_hw_numtxpending(struct ath_hal * ah,uint32_t q)151 ath9k_hw_numtxpending(struct ath_hal *ah, uint32_t q)
152 {
153 uint32_t npend;
154
155 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
156 if (npend == 0) {
157
158 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
159 npend = 1;
160 }
161
162 return (npend);
163 }
164
165 boolean_t
ath9k_hw_updatetxtriglevel(struct ath_hal * ah,boolean_t bIncTrigLevel)166 ath9k_hw_updatetxtriglevel(struct ath_hal *ah, boolean_t bIncTrigLevel)
167 {
168 struct ath_hal_5416 *ahp = AH5416(ah);
169 uint32_t txcfg, curLevel, newLevel;
170 enum ath9k_int omask;
171
172 if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
173 return (B_FALSE);
174
175 omask = ath9k_hw_set_interrupts(ah,
176 ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
177
178 txcfg = REG_READ(ah, AR_TXCFG);
179 curLevel = MS(txcfg, AR_FTRIG);
180 newLevel = curLevel;
181 if (bIncTrigLevel) {
182 if (curLevel < MAX_TX_FIFO_THRESHOLD)
183 newLevel++;
184 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
185 newLevel--;
186 if (newLevel != curLevel)
187 REG_WRITE(ah, AR_TXCFG,
188 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
189
190 (void) ath9k_hw_set_interrupts(ah, omask);
191
192 ah->ah_txTrigLevel = (uint16_t)newLevel; /* ??? */
193
194 return (newLevel != curLevel);
195 }
196
197 boolean_t
ath9k_hw_stoptxdma(struct ath_hal * ah,uint32_t q)198 ath9k_hw_stoptxdma(struct ath_hal *ah, uint32_t q)
199 {
200 uint32_t tsfLow, j, wait;
201
202 REG_WRITE(ah, AR_Q_TXD, 1 << q);
203
204 for (wait = 1000; wait != 0; wait--) {
205 if (ath9k_hw_numtxpending(ah, q) == 0)
206 break;
207 drv_usecwait(100);
208 }
209
210 if (ath9k_hw_numtxpending(ah, q)) {
211 ARN_DBG((ARN_DBG_QUEUE,
212 "%s: Num of pending TX Frames %d on Q %d\n",
213 __func__, ath9k_hw_numtxpending(ah, q), q));
214
215 for (j = 0; j < 2; j++) {
216 tsfLow = REG_READ(ah, AR_TSF_L32);
217 REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR));
218 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
219 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
220 REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
221
222 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
223 break;
224 ARN_DBG((ARN_DBG_QUEUE,
225 "%s: TSF have moved while trying to set "
226 "quiet time TSF: 0x%08x\n",
227 __func__, tsfLow));
228 }
229
230 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
231
232 drv_usecwait(200);
233 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
234
235 wait = 1000;
236
237 while (ath9k_hw_numtxpending(ah, q)) {
238 if ((--wait) == 0) {
239 ARN_DBG((ARN_DBG_XMIT,
240 "%s: Failed to stop Tx DMA in 100 "
241 "msec after killing last frame\n",
242 __func__));
243 break;
244 }
245 drv_usecwait(100);
246 }
247
248 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
249 }
250
251 REG_WRITE(ah, AR_Q_TXD, 0);
252
253 return (wait != 0);
254 }
255
256 /* ARGSUSED */
257 boolean_t
ath9k_hw_filltxdesc(struct ath_hal * ah,struct ath_desc * ds,uint32_t segLen,boolean_t firstSeg,boolean_t lastSeg,const struct ath_desc * ds0)258 ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
259 uint32_t segLen, boolean_t firstSeg,
260 boolean_t lastSeg, const struct ath_desc *ds0)
261 {
262 struct ar5416_desc *ads = AR5416DESC(ds);
263
264 if (firstSeg) {
265 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
266 } else if (lastSeg) {
267 ads->ds_ctl0 = 0;
268 ads->ds_ctl1 = segLen;
269 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
270 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
271 } else {
272 ads->ds_ctl0 = 0;
273 ads->ds_ctl1 = segLen | AR_TxMore;
274 ads->ds_ctl2 = 0;
275 ads->ds_ctl3 = 0;
276 }
277 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
278 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
279 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
280 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
281 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
282
283 return (B_TRUE);
284 }
285
286 /* ARGSUSED */
287 void
ath9k_hw_cleartxdesc(struct ath_hal * ah,struct ath_desc * ds)288 ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
289 {
290 struct ar5416_desc *ads = AR5416DESC(ds);
291
292 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
293 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
294 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
295 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
296 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
297 }
298
299 int
ath9k_hw_txprocdesc(struct ath_hal * ah,struct ath_desc * ds)300 ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
301 {
302 struct ar5416_desc *ads = AR5416DESC(ds);
303
304 if ((ads->ds_txstatus9 & AR_TxDone) == 0)
305 return (EINPROGRESS);
306
307 ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
308 ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
309 ds->ds_txstat.ts_status = 0;
310 ds->ds_txstat.ts_flags = 0;
311
312 if (ads->ds_txstatus1 & AR_ExcessiveRetries) {
313 ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_XRETRY\n"));
314 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
315 }
316 if (ads->ds_txstatus1 & AR_Filtered) {
317 ARN_DBG((ARN_DBG_INTERRUPT, "arn: AR_Filtered\n"));
318 ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
319 }
320 if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
321 ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_FIFO\n"));
322 ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
323 (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
324 }
325 if (ads->ds_txstatus9 & AR_TxOpExceeded) {
326 ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_XTXOP\n"));
327 ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
328 }
329 if (ads->ds_txstatus1 & AR_TxTimerExpired) {
330 ARN_DBG((ARN_DBG_INTERRUPT,
331 "arn: ATH9K_TXERR_TIMER_EXPIRED\n"));
332 ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
333 }
334
335 if (ads->ds_txstatus1 & AR_DescCfgErr) {
336 ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TX_DESC_CFG_ERR\n"));
337 ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
338 }
339 if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
340 ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
341 (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
342 }
343 if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
344 ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
345 (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
346 }
347 if (ads->ds_txstatus0 & AR_TxBaStatus) {
348 ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
349 ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
350 ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
351 }
352
353 ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
354 switch (ds->ds_txstat.ts_rateindex) {
355 case 0:
356 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
357 break;
358 case 1:
359 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
360 break;
361 case 2:
362 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
363 break;
364 case 3:
365 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
366 break;
367 }
368
369 ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
370 ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
371 ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
372 ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
373 ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
374 ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
375 ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
376 ds->ds_txstat.evm0 = ads->AR_TxEVM0;
377 ds->ds_txstat.evm1 = ads->AR_TxEVM1;
378 ds->ds_txstat.evm2 = ads->AR_TxEVM2;
379 ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
380 ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
381 ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
382 ds->ds_txstat.ts_antenna = 1;
383
384 return (0);
385 }
386
387 void
ath9k_hw_set11n_txdesc(struct ath_hal * ah,struct ath_desc * ds,uint32_t pktLen,enum ath9k_pkt_type type,uint32_t txPower,uint32_t keyIx,enum ath9k_key_type keyType,uint32_t flags)388 ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
389 uint32_t pktLen, enum ath9k_pkt_type type, uint32_t txPower,
390 uint32_t keyIx, enum ath9k_key_type keyType, uint32_t flags)
391 {
392 struct ar5416_desc *ads = AR5416DESC(ds);
393 struct ath_hal_5416 *ahp = AH5416(ah);
394
395 txPower += ahp->ah_txPowerIndexOffset;
396 if (txPower > 63)
397 txPower = 63;
398
399 ads->ds_ctl0 = (pktLen & AR_FrameLen) |
400 (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
401 SM(txPower, AR_XmitPower) |
402 (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
403 (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) |
404 (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
405 (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
406
407 ads->ds_ctl1 =
408 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) |
409 SM(type, AR_FrameType) |
410 (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) |
411 (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) |
412 (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
413
414 ads->ds_ctl6 = SM(keyType, AR_EncrType);
415
416 if (AR_SREV_9285(ah)) {
417 ads->ds_ctl8 = 0;
418 ads->ds_ctl9 = 0;
419 ads->ds_ctl10 = 0;
420 ads->ds_ctl11 = 0;
421 }
422
423 }
424
425 /* ARGSUSED */
426 void
ath9k_hw_set11n_ratescenario(struct ath_hal * ah,struct ath_desc * ds,struct ath_desc * lastds,uint32_t durUpdateEn,uint32_t rtsctsRate,uint32_t rtsctsDuration,struct ath9k_11n_rate_series series[],uint32_t nseries,uint32_t flags)427 ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
428 struct ath_desc *lastds,
429 uint32_t durUpdateEn, uint32_t rtsctsRate,
430 uint32_t rtsctsDuration,
431 struct ath9k_11n_rate_series series[],
432 uint32_t nseries, uint32_t flags)
433 {
434 struct ar5416_desc *ads = AR5416DESC(ds);
435 struct ar5416_desc *last_ads = AR5416DESC(lastds);
436 uint32_t ds_ctl0;
437
438 (void) nseries;
439 (void) rtsctsDuration;
440
441 if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
442 ds_ctl0 = ads->ds_ctl0;
443
444 if (flags & ATH9K_TXDESC_RTSENA) {
445 ds_ctl0 &= ~AR_CTSEnable;
446 ds_ctl0 |= AR_RTSEnable;
447 } else {
448 ds_ctl0 &= ~AR_RTSEnable;
449 ds_ctl0 |= AR_CTSEnable;
450 }
451
452 ads->ds_ctl0 = ds_ctl0;
453 } else {
454 ads->ds_ctl0 =
455 (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
456 }
457
458 ads->ds_ctl2 = set11nTries(series, 0) |
459 set11nTries(series, 1) |
460 set11nTries(series, 2) |
461 set11nTries(series, 3) |
462 (durUpdateEn ? AR_DurUpdateEna : 0) |
463 SM(0, AR_BurstDur);
464
465 ads->ds_ctl3 = set11nRate(series, 0) |
466 set11nRate(series, 1) |
467 set11nRate(series, 2) |
468 set11nRate(series, 3);
469
470 ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) |
471 set11nPktDurRTSCTS(series, 1);
472
473 ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) |
474 set11nPktDurRTSCTS(series, 3);
475
476 ads->ds_ctl7 = set11nRateFlags(series, 0) |
477 set11nRateFlags(series, 1) |
478 set11nRateFlags(series, 2) |
479 set11nRateFlags(series, 3) |
480 SM(rtsctsRate, AR_RTSCTSRate);
481 last_ads->ds_ctl2 = ads->ds_ctl2;
482 last_ads->ds_ctl3 = ads->ds_ctl3;
483 }
484
485 /* ARGSUSED */
486 void
ath9k_hw_set11n_aggr_first(struct ath_hal * ah,struct ath_desc * ds,uint32_t aggrLen)487 ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
488 uint32_t aggrLen)
489 {
490 struct ar5416_desc *ads = AR5416DESC(ds);
491
492 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
493 ads->ds_ctl6 &= ~AR_AggrLen;
494 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
495 }
496
497 /* ARGSUSED */
498 void
ath9k_hw_set11n_aggr_middle(struct ath_hal * ah,struct ath_desc * ds,uint32_t numDelims)499 ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
500 uint32_t numDelims)
501 {
502 struct ar5416_desc *ads = AR5416DESC(ds);
503 unsigned int ctl6;
504
505 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
506
507 ctl6 = ads->ds_ctl6;
508 ctl6 &= ~AR_PadDelim;
509 ctl6 |= SM(numDelims, AR_PadDelim);
510 ads->ds_ctl6 = ctl6;
511 }
512
513 /* ARGSUSED */
514 void
ath9k_hw_set11n_aggr_last(struct ath_hal * ah,struct ath_desc * ds)515 ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
516 {
517 struct ar5416_desc *ads = AR5416DESC(ds);
518
519 ads->ds_ctl1 |= AR_IsAggr;
520 ads->ds_ctl1 &= ~AR_MoreAggr;
521 ads->ds_ctl6 &= ~AR_PadDelim;
522 }
523
524 /* ARGSUSED */
525 void
ath9k_hw_clr11n_aggr(struct ath_hal * ah,struct ath_desc * ds)526 ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
527 {
528 struct ar5416_desc *ads = AR5416DESC(ds);
529
530 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
531 }
532
533 /* ARGSUSED */
534 void
ath9k_hw_set11n_burstduration(struct ath_hal * ah,struct ath_desc * ds,uint32_t burstDuration)535 ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
536 uint32_t burstDuration)
537 {
538 struct ar5416_desc *ads = AR5416DESC(ds);
539
540 ads->ds_ctl2 &= ~AR_BurstDur;
541 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
542 }
543
544 /* ARGSUSED */
545 void
ath9k_hw_set11n_virtualmorefrag(struct ath_hal * ah,struct ath_desc * ds,uint32_t vmf)546 ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
547 uint32_t vmf)
548 {
549 struct ar5416_desc *ads = AR5416DESC(ds);
550
551 if (vmf)
552 ads->ds_ctl0 |= AR_VirtMoreFrag;
553 else
554 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
555 }
556
557 void
ath9k_hw_gettxintrtxqs(struct ath_hal * ah,uint32_t * txqs)558 ath9k_hw_gettxintrtxqs(struct ath_hal *ah, uint32_t *txqs)
559 {
560 struct ath_hal_5416 *ahp = AH5416(ah);
561
562 *txqs &= ahp->ah_intrTxqs;
563 ahp->ah_intrTxqs &= ~(*txqs);
564 }
565
566 boolean_t
ath9k_hw_set_txq_props(struct ath_hal * ah,int q,const struct ath9k_tx_queue_info * qinfo)567 ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
568 const struct ath9k_tx_queue_info *qinfo)
569 {
570 uint32_t cw;
571 struct ath_hal_5416 *ahp = AH5416(ah);
572 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
573 struct ath9k_tx_queue_info *qi;
574
575 if (q >= pCap->total_queues) {
576 ARN_DBG((ARN_DBG_QUEUE, "%s: invalid queue num %u\n",
577 __func__, q));
578 return (B_FALSE);
579 }
580
581 qi = &ahp->ah_txq[q];
582 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
583 ARN_DBG((ARN_DBG_QUEUE, "%s: inactive queue\n",
584 __func__));
585 return (B_FALSE);
586 }
587
588 ARN_DBG((ARN_DBG_QUEUE, "%s: queue %p\n", __func__, qi));
589
590 qi->tqi_ver = qinfo->tqi_ver;
591 qi->tqi_subtype = qinfo->tqi_subtype;
592 qi->tqi_qflags = qinfo->tqi_qflags;
593 qi->tqi_priority = qinfo->tqi_priority;
594 if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
595 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
596 else
597 qi->tqi_aifs = INIT_AIFS;
598 if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
599 cw = min(qinfo->tqi_cwmin, 1024U);
600 qi->tqi_cwmin = 1;
601 while (qi->tqi_cwmin < cw)
602 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
603 } else
604 qi->tqi_cwmin = qinfo->tqi_cwmin;
605 if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
606 cw = min(qinfo->tqi_cwmax, 1024U);
607 qi->tqi_cwmax = 1;
608 while (qi->tqi_cwmax < cw)
609 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
610 } else
611 qi->tqi_cwmax = INIT_CWMAX;
612
613 if (qinfo->tqi_shretry != 0)
614 qi->tqi_shretry = min((uint32_t)qinfo->tqi_shretry, 15U);
615 else
616 qi->tqi_shretry = INIT_SH_RETRY;
617 if (qinfo->tqi_lgretry != 0)
618 qi->tqi_lgretry = min((uint32_t)qinfo->tqi_lgretry, 15U);
619 else
620 qi->tqi_lgretry = INIT_LG_RETRY;
621 qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
622 qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
623 qi->tqi_burstTime = qinfo->tqi_burstTime;
624 qi->tqi_readyTime = qinfo->tqi_readyTime;
625
626 switch (qinfo->tqi_subtype) {
627 case ATH9K_WME_UPSD:
628 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
629 qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
630 break;
631 default:
632 break;
633 }
634
635 return (B_TRUE);
636 }
637
638 boolean_t
ath9k_hw_get_txq_props(struct ath_hal * ah,int q,struct ath9k_tx_queue_info * qinfo)639 ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
640 struct ath9k_tx_queue_info *qinfo)
641 {
642 struct ath_hal_5416 *ahp = AH5416(ah);
643 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
644 struct ath9k_tx_queue_info *qi;
645
646 if (q >= pCap->total_queues) {
647 ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_get_txq_props(): "
648 "invalid queue num %u\n", q));
649 return (B_FALSE);
650 }
651
652 qi = &ahp->ah_txq[q];
653 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
654 ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_get_txq_props(): "
655 "inactive queue\n"));
656 return (B_FALSE);
657 }
658
659 qinfo->tqi_qflags = qi->tqi_qflags;
660 qinfo->tqi_ver = qi->tqi_ver;
661 qinfo->tqi_subtype = qi->tqi_subtype;
662 qinfo->tqi_qflags = qi->tqi_qflags;
663 qinfo->tqi_priority = qi->tqi_priority;
664 qinfo->tqi_aifs = qi->tqi_aifs;
665 qinfo->tqi_cwmin = qi->tqi_cwmin;
666 qinfo->tqi_cwmax = qi->tqi_cwmax;
667 qinfo->tqi_shretry = qi->tqi_shretry;
668 qinfo->tqi_lgretry = qi->tqi_lgretry;
669 qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
670 qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
671 qinfo->tqi_burstTime = qi->tqi_burstTime;
672 qinfo->tqi_readyTime = qi->tqi_readyTime;
673
674 return (B_TRUE);
675 }
676
677 int
ath9k_hw_setuptxqueue(struct ath_hal * ah,enum ath9k_tx_queue type,const struct ath9k_tx_queue_info * qinfo)678 ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
679 const struct ath9k_tx_queue_info *qinfo)
680 {
681 struct ath_hal_5416 *ahp = AH5416(ah);
682 struct ath9k_tx_queue_info *qi;
683 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
684 int q;
685
686 switch (type) {
687 case ATH9K_TX_QUEUE_BEACON:
688 q = pCap->total_queues - 1;
689 break;
690 case ATH9K_TX_QUEUE_CAB:
691 q = pCap->total_queues - 2;
692 break;
693 case ATH9K_TX_QUEUE_PSPOLL:
694 q = 1;
695 break;
696 case ATH9K_TX_QUEUE_UAPSD:
697 q = pCap->total_queues - 3;
698 break;
699 case ATH9K_TX_QUEUE_DATA:
700 for (q = 0; q < pCap->total_queues; q++)
701 if (ahp->ah_txq[q].tqi_type ==
702 ATH9K_TX_QUEUE_INACTIVE)
703 break;
704 if (q == pCap->total_queues) {
705 ARN_DBG((ARN_DBG_QUEUE,
706 "arn: ath9k_hw_setuptxqueue(): "
707 "no available tx queue\n"));
708 return (-1);
709 }
710 break;
711 default:
712 ARN_DBG((ARN_DBG_QUEUE,
713 "arn: ath9k_hw_setuptxqueue(): "
714 "bad tx queue type %u\n", type));
715
716 return (-1);
717 }
718
719 ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_setuptxqueue(): "
720 "queue %u\n", q));
721
722 qi = &ahp->ah_txq[q];
723 if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
724 ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_setuptxqueue(): "
725 "tx queue %u already active\n", q));
726
727 return (-1);
728 }
729 (void) memset(qi, 0, sizeof (struct ath9k_tx_queue_info));
730 qi->tqi_type = type;
731 if (qinfo == NULL) {
732 qi->tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
733 TXQ_FLAG_TXERRINT_ENABLE |
734 TXQ_FLAG_TXDESCINT_ENABLE |
735 TXQ_FLAG_TXURNINT_ENABLE;
736 qi->tqi_aifs = INIT_AIFS;
737 qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
738 qi->tqi_cwmax = INIT_CWMAX;
739 qi->tqi_shretry = INIT_SH_RETRY;
740 qi->tqi_lgretry = INIT_LG_RETRY;
741 qi->tqi_physCompBuf = 0;
742 } else {
743 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
744 (void) ath9k_hw_set_txq_props(ah, q, qinfo);
745 }
746
747 return (q);
748 }
749
750 boolean_t
ath9k_hw_releasetxqueue(struct ath_hal * ah,uint32_t q)751 ath9k_hw_releasetxqueue(struct ath_hal *ah, uint32_t q)
752 {
753 struct ath_hal_5416 *ahp = AH5416(ah);
754 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
755 struct ath9k_tx_queue_info *qi;
756
757 if (q >= pCap->total_queues) {
758 ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
759 "invalid queue num %u\n", q));
760 return (B_FALSE);
761 }
762 qi = &ahp->ah_txq[q];
763 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
764 ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
765 "inactive queue %u\n", q));
766 return (B_FALSE);
767 }
768
769 ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
770 "release queue %u\n", q));
771
772
773 qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
774 ahp->ah_txOkInterruptMask &= ~(1 << q);
775 ahp->ah_txErrInterruptMask &= ~(1 << q);
776 ahp->ah_txDescInterruptMask &= ~(1 << q);
777 ahp->ah_txEolInterruptMask &= ~(1 << q);
778 ahp->ah_txUrnInterruptMask &= ~(1 << q);
779 ath9k_hw_set_txq_interrupts(ah, qi);
780
781 return (B_TRUE);
782 }
783
784 boolean_t
ath9k_hw_resettxqueue(struct ath_hal * ah,uint32_t q)785 ath9k_hw_resettxqueue(struct ath_hal *ah, uint32_t q)
786 {
787 struct ath_hal_5416 *ahp = AH5416(ah);
788 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
789 struct ath9k_channel *chan = ah->ah_curchan;
790 struct ath9k_tx_queue_info *qi;
791 uint32_t cwMin, chanCwMin, value;
792
793 if (q >= pCap->total_queues) {
794 ARN_DBG((ARN_DBG_QUEUE, "%s: invalid queue num %u\n",
795 __func__, q));
796
797 return (B_FALSE);
798 }
799
800 qi = &ahp->ah_txq[q];
801 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
802 ARN_DBG((ARN_DBG_QUEUE, "%s: inactive queue %u\n",
803 __func__, q));
804
805 return (B_TRUE);
806 }
807
808 ARN_DBG((ARN_DBG_QUEUE,
809 "%s: reset queue %u\n", __func__, q));
810
811 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
812 if (chan && IS_CHAN_B(chan))
813 chanCwMin = INIT_CWMIN_11B;
814 else
815 chanCwMin = INIT_CWMIN;
816
817 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) {
818 /* Nothing to do */
819 }
820 } else
821 cwMin = qi->tqi_cwmin;
822
823 REG_WRITE(ah, AR_DLCL_IFS(q),
824 SM(cwMin, AR_D_LCL_IFS_CWMIN) |
825 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
826 SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
827
828 REG_WRITE(ah, AR_DRETRY_LIMIT(q),
829 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
830 SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
831 SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
832
833 REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
834 REG_WRITE(ah, AR_DMISC(q),
835 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
836
837 if (qi->tqi_cbrPeriod) {
838 REG_WRITE(ah, AR_QCBRCFG(q),
839 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
840 SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
841 REG_WRITE(ah, AR_QMISC(q),
842 REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
843 (qi->tqi_cbrOverflowLimit ?
844 AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
845 }
846 if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
847 REG_WRITE(ah, AR_QRDYTIMECFG(q),
848 SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
849 AR_Q_RDYTIMECFG_EN);
850 }
851
852 REG_WRITE(ah, AR_DCHNTIME(q),
853 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
854 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
855
856 if (qi->tqi_burstTime &&
857 (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
858 REG_WRITE(ah, AR_QMISC(q),
859 REG_READ(ah, AR_QMISC(q)) |
860 AR_Q_MISC_RDYTIME_EXP_POLICY);
861
862 }
863
864 if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
865 REG_WRITE(ah, AR_DMISC(q),
866 REG_READ(ah, AR_DMISC(q)) |
867 AR_D_MISC_POST_FR_BKOFF_DIS);
868 }
869 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
870 REG_WRITE(ah, AR_DMISC(q),
871 REG_READ(ah, AR_DMISC(q)) |
872 AR_D_MISC_FRAG_BKOFF_EN);
873 }
874 switch (qi->tqi_type) {
875 case ATH9K_TX_QUEUE_BEACON:
876 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) |
877 AR_Q_MISC_FSP_DBA_GATED |
878 AR_Q_MISC_BEACON_USE |
879 AR_Q_MISC_CBR_INCR_DIS1);
880
881 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
882 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
883 AR_D_MISC_ARB_LOCKOUT_CNTRL_S) |
884 AR_D_MISC_BEACON_USE |
885 AR_D_MISC_POST_FR_BKOFF_DIS);
886 break;
887 case ATH9K_TX_QUEUE_CAB:
888 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) |
889 AR_Q_MISC_FSP_DBA_GATED |
890 AR_Q_MISC_CBR_INCR_DIS1 |
891 AR_Q_MISC_CBR_INCR_DIS0);
892 value = (qi->tqi_readyTime -
893 (ah->ah_config.sw_beacon_response_time -
894 ah->ah_config.dma_beacon_response_time) -
895 ah->ah_config.additional_swba_backoff) * 1024;
896 REG_WRITE(ah, AR_QRDYTIMECFG(q),
897 value | AR_Q_RDYTIMECFG_EN);
898 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
899 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
900 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
901 break;
902 case ATH9K_TX_QUEUE_PSPOLL:
903 REG_WRITE(ah, AR_QMISC(q),
904 REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
905 break;
906 case ATH9K_TX_QUEUE_UAPSD:
907 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
908 AR_D_MISC_POST_FR_BKOFF_DIS);
909 break;
910 default:
911 break;
912 }
913
914 if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
915 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
916 SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
917 AR_D_MISC_ARB_LOCKOUT_CNTRL) |
918 AR_D_MISC_POST_FR_BKOFF_DIS);
919 }
920
921 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
922 ahp->ah_txOkInterruptMask |= 1 << q;
923 else
924 ahp->ah_txOkInterruptMask &= ~(1 << q);
925 if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
926 ahp->ah_txErrInterruptMask |= 1 << q;
927 else
928 ahp->ah_txErrInterruptMask &= ~(1 << q);
929 if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
930 ahp->ah_txDescInterruptMask |= 1 << q;
931 else
932 ahp->ah_txDescInterruptMask &= ~(1 << q);
933 if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
934 ahp->ah_txEolInterruptMask |= 1 << q;
935 else
936 ahp->ah_txEolInterruptMask &= ~(1 << q);
937 if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
938 ahp->ah_txUrnInterruptMask |= 1 << q;
939 else
940 ahp->ah_txUrnInterruptMask &= ~(1 << q);
941 ath9k_hw_set_txq_interrupts(ah, qi);
942
943 return (B_TRUE);
944 }
945
946 /* ARGSUSED */
947 int
ath9k_hw_rxprocdesc(struct ath_hal * ah,struct ath_desc * ds,uint32_t pa,struct ath_desc * nds,uint64_t tsf)948 ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
949 uint32_t pa,
950 struct ath_desc *nds,
951 uint64_t tsf)
952 {
953 struct ar5416_desc ads;
954 struct ar5416_desc *adsp = AR5416DESC(ds);
955 uint32_t phyerr;
956
957 if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
958 return (EINPROGRESS);
959
960 ads.u.rx = adsp->u.rx;
961
962 ds->ds_rxstat.rs_status = 0;
963 ds->ds_rxstat.rs_flags = 0;
964
965 ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
966 ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
967
968 ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
969 ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
970 ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
971 ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
972 ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
973 ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
974 ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
975 if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
976 ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
977 else
978 ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
979
980 ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
981 ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
982
983 ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
984 ds->ds_rxstat.rs_moreaggr =
985 (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
986 ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
987 ds->ds_rxstat.rs_flags =
988 (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
989 ds->ds_rxstat.rs_flags |=
990 (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
991
992 if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
993 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
994 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
995 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
996 if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
997 ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
998
999 if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
1000 if (ads.ds_rxstatus8 & AR_CRCErr)
1001 ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
1002 else if (ads.ds_rxstatus8 & AR_PHYErr) {
1003 ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
1004 phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
1005 ds->ds_rxstat.rs_phyerr = (uint8_t)phyerr; /* LINT */
1006 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
1007 ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
1008 else if (ads.ds_rxstatus8 & AR_MichaelErr)
1009 ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
1010 }
1011
1012 return (0);
1013 }
1014
1015 boolean_t
ath9k_hw_setuprxdesc(struct ath_hal * ah,struct ath_desc * ds,uint32_t size,uint32_t flags)1016 ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
1017 uint32_t size, uint32_t flags)
1018 {
1019 struct ar5416_desc *ads = AR5416DESC(ds);
1020 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
1021
1022 ads->ds_ctl1 = size & AR_BufLen;
1023 if (flags & ATH9K_RXDESC_INTREQ)
1024 ads->ds_ctl1 |= AR_RxIntrReq;
1025
1026 ads->ds_rxstatus8 &= ~AR_RxDone;
1027 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
1028 (void) memset(&(ads->u), 0, sizeof (ads->u));
1029
1030 return (B_TRUE);
1031 }
1032
1033 boolean_t
ath9k_hw_setrxabort(struct ath_hal * ah,boolean_t set)1034 ath9k_hw_setrxabort(struct ath_hal *ah, boolean_t set)
1035 {
1036 uint32_t reg;
1037
1038 if (set) {
1039 REG_SET_BIT(ah, AR_DIAG_SW,
1040 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1041
1042 if (!ath9k_hw_wait(ah, AR_OBS_BUS_1,
1043 AR_OBS_BUS_1_RX_STATE, 0)) {
1044 REG_CLR_BIT(ah, AR_DIAG_SW,
1045 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1046
1047 reg = REG_READ(ah, AR_OBS_BUS_1);
1048
1049 ARN_DBG((ARN_DBG_FATAL,
1050 "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
1051 __func__, reg));
1052
1053 return (B_FALSE);
1054 }
1055 } else {
1056 REG_CLR_BIT(ah, AR_DIAG_SW,
1057 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1058 }
1059
1060 return (B_TRUE);
1061 }
1062
1063 void
ath9k_hw_putrxbuf(struct ath_hal * ah,uint32_t rxdp)1064 ath9k_hw_putrxbuf(struct ath_hal *ah, uint32_t rxdp)
1065 {
1066 REG_WRITE(ah, AR_RXDP, rxdp);
1067 }
1068
1069 void
ath9k_hw_rxena(struct ath_hal * ah)1070 ath9k_hw_rxena(struct ath_hal *ah)
1071 {
1072 REG_WRITE(ah, AR_CR, AR_CR_RXE);
1073 }
1074
1075 void
ath9k_hw_startpcureceive(struct ath_hal * ah)1076 ath9k_hw_startpcureceive(struct ath_hal *ah)
1077 {
1078 ath9k_enable_mib_counters(ah);
1079
1080 ath9k_ani_reset(ah);
1081
1082 REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1083 }
1084
1085 void
ath9k_hw_stoppcurecv(struct ath_hal * ah)1086 ath9k_hw_stoppcurecv(struct ath_hal *ah)
1087 {
1088 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
1089
1090 ath9k_hw_disable_mib_counters(ah);
1091 }
1092
1093 boolean_t
ath9k_hw_stopdmarecv(struct ath_hal * ah)1094 ath9k_hw_stopdmarecv(struct ath_hal *ah)
1095 {
1096 REG_WRITE(ah, AR_CR, AR_CR_RXD);
1097
1098 if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
1099 ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_stopdmarecv(): "
1100 "dma failed to stop in 10ms\n"
1101 "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
1102 REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)));
1103 return (B_FALSE);
1104 } else {
1105 return (B_TRUE);
1106 }
1107 }
1108