aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/mac.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c508
1 files changed, 255 insertions, 253 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 4a36ec53f73..22fa5125abf 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -183,226 +183,25 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
183 return true; 183 return true;
184} 184}
185 185
186void ar9002_hw_attach_mac_ops(struct ath_hw *ah) 186static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
187{ 187 bool is_firstseg, bool is_lastseg,
188 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 188 const void *ds0, dma_addr_t buf_addr,
189 189 unsigned int qcu)
190 ops->rx_enable = ar9002_hw_rx_enable;
191 ops->set_desc_link = ar9002_hw_set_desc_link;
192 ops->get_desc_link = ar9002_hw_get_desc_link;
193 ops->get_isr = ar9002_hw_get_isr;
194}
195
196static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
197 struct ath9k_tx_queue_info *qi)
198{
199 ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
200 "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
201 ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
202 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
203 ah->txurn_interrupt_mask);
204
205 REG_WRITE(ah, AR_IMR_S0,
206 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
207 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
208 REG_WRITE(ah, AR_IMR_S1,
209 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
210 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
211
212 ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
213 ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
214 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
215}
216
217u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
218{
219 return REG_READ(ah, AR_QTXDP(q));
220}
221EXPORT_SYMBOL(ath9k_hw_gettxbuf);
222
223void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
224{
225 REG_WRITE(ah, AR_QTXDP(q), txdp);
226}
227EXPORT_SYMBOL(ath9k_hw_puttxbuf);
228
229void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
230{
231 ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE,
232 "Enable TXE on queue: %u\n", q);
233 REG_WRITE(ah, AR_Q_TXE, 1 << q);
234}
235EXPORT_SYMBOL(ath9k_hw_txstart);
236
237u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
238{
239 u32 npend;
240
241 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
242 if (npend == 0) {
243
244 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
245 npend = 1;
246 }
247
248 return npend;
249}
250EXPORT_SYMBOL(ath9k_hw_numtxpending);
251
252/**
253 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
254 *
255 * @ah: atheros hardware struct
256 * @bIncTrigLevel: whether or not the frame trigger level should be updated
257 *
258 * The frame trigger level specifies the minimum number of bytes,
259 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
260 * before the PCU will initiate sending the frame on the air. This can
261 * mean we initiate transmit before a full frame is on the PCU TX FIFO.
262 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
263 * first)
264 *
265 * Caution must be taken to ensure to set the frame trigger level based
266 * on the DMA request size. For example if the DMA request size is set to
267 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
268 * there need to be enough space in the tx FIFO for the requested transfer
269 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
270 * the threshold to a value beyond 6, then the transmit will hang.
271 *
272 * Current dual stream devices have a PCU TX FIFO size of 8 KB.
273 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
274 * there is a hardware issue which forces us to use 2 KB instead so the
275 * frame trigger level must not exceed 2 KB for these chipsets.
276 */
277bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
278{
279 u32 txcfg, curLevel, newLevel;
280 enum ath9k_int omask;
281
282 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
283 return false;
284
285 omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
286
287 txcfg = REG_READ(ah, AR_TXCFG);
288 curLevel = MS(txcfg, AR_FTRIG);
289 newLevel = curLevel;
290 if (bIncTrigLevel) {
291 if (curLevel < ah->config.max_txtrig_level)
292 newLevel++;
293 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
294 newLevel--;
295 if (newLevel != curLevel)
296 REG_WRITE(ah, AR_TXCFG,
297 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
298
299 ath9k_hw_set_interrupts(ah, omask);
300
301 ah->tx_trig_level = newLevel;
302
303 return newLevel != curLevel;
304}
305EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
306
307bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
308{
309#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
310#define ATH9K_TIME_QUANTUM 100 /* usec */
311 struct ath_common *common = ath9k_hw_common(ah);
312 struct ath9k_hw_capabilities *pCap = &ah->caps;
313 struct ath9k_tx_queue_info *qi;
314 u32 tsfLow, j, wait;
315 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
316
317 if (q >= pCap->total_queues) {
318 ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
319 "invalid queue: %u\n", q);
320 return false;
321 }
322
323 qi = &ah->txq[q];
324 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
325 ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
326 "inactive queue: %u\n", q);
327 return false;
328 }
329
330 REG_WRITE(ah, AR_Q_TXD, 1 << q);
331
332 for (wait = wait_time; wait != 0; wait--) {
333 if (ath9k_hw_numtxpending(ah, q) == 0)
334 break;
335 udelay(ATH9K_TIME_QUANTUM);
336 }
337
338 if (ath9k_hw_numtxpending(ah, q)) {
339 ath_print(common, ATH_DBG_QUEUE,
340 "%s: Num of pending TX Frames %d on Q %d\n",
341 __func__, ath9k_hw_numtxpending(ah, q), q);
342
343 for (j = 0; j < 2; j++) {
344 tsfLow = REG_READ(ah, AR_TSF_L32);
345 REG_WRITE(ah, AR_QUIET2,
346 SM(10, AR_QUIET2_QUIET_DUR));
347 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
348 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
349 REG_SET_BIT(ah, AR_TIMER_MODE,
350 AR_QUIET_TIMER_EN);
351
352 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
353 break;
354
355 ath_print(common, ATH_DBG_QUEUE,
356 "TSF has moved while trying to set "
357 "quiet time TSF: 0x%08x\n", tsfLow);
358 }
359
360 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
361
362 udelay(200);
363 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
364
365 wait = wait_time;
366 while (ath9k_hw_numtxpending(ah, q)) {
367 if ((--wait) == 0) {
368 ath_print(common, ATH_DBG_FATAL,
369 "Failed to stop TX DMA in 100 "
370 "msec after killing last frame\n");
371 break;
372 }
373 udelay(ATH9K_TIME_QUANTUM);
374 }
375
376 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
377 }
378
379 REG_WRITE(ah, AR_Q_TXD, 0);
380 return wait != 0;
381
382#undef ATH9K_TX_STOP_DMA_TIMEOUT
383#undef ATH9K_TIME_QUANTUM
384}
385EXPORT_SYMBOL(ath9k_hw_stoptxdma);
386
387void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
388 u32 segLen, bool firstSeg,
389 bool lastSeg, const struct ath_desc *ds0,
390 dma_addr_t buf_addr)
391{ 190{
392 struct ar5416_desc *ads = AR5416DESC(ds); 191 struct ar5416_desc *ads = AR5416DESC(ds);
393 192
394 ads->ds_data = buf_addr; 193 ads->ds_data = buf_addr;
395 194
396 if (firstSeg) { 195 if (is_firstseg) {
397 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); 196 ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
398 } else if (lastSeg) { 197 } else if (is_lastseg) {
399 ads->ds_ctl0 = 0; 198 ads->ds_ctl0 = 0;
400 ads->ds_ctl1 = segLen; 199 ads->ds_ctl1 = seglen;
401 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; 200 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
402 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; 201 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
403 } else { 202 } else {
404 ads->ds_ctl0 = 0; 203 ads->ds_ctl0 = 0;
405 ads->ds_ctl1 = segLen | AR_TxMore; 204 ads->ds_ctl1 = seglen | AR_TxMore;
406 ads->ds_ctl2 = 0; 205 ads->ds_ctl2 = 0;
407 ads->ds_ctl3 = 0; 206 ads->ds_ctl3 = 0;
408 } 207 }
@@ -412,22 +211,9 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
412 ads->ds_txstatus6 = ads->ds_txstatus7 = 0; 211 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
413 ads->ds_txstatus8 = ads->ds_txstatus9 = 0; 212 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
414} 213}
415EXPORT_SYMBOL(ath9k_hw_filltxdesc);
416 214
417void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) 215static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
418{ 216 struct ath_tx_status *ts)
419 struct ar5416_desc *ads = AR5416DESC(ds);
420
421 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
422 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
423 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
424 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
425 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
426}
427EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
428
429int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
430 struct ath_tx_status *ts)
431{ 217{
432 struct ar5416_desc *ads = AR5416DESC(ds); 218 struct ar5416_desc *ads = AR5416DESC(ds);
433 219
@@ -503,11 +289,11 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
503 289
504 return 0; 290 return 0;
505} 291}
506EXPORT_SYMBOL(ath9k_hw_txprocdesc);
507 292
508void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, 293static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
509 u32 pktLen, enum ath9k_pkt_type type, u32 txPower, 294 u32 pktLen, enum ath9k_pkt_type type,
510 u32 keyIx, enum ath9k_key_type keyType, u32 flags) 295 u32 txPower, u32 keyIx,
296 enum ath9k_key_type keyType, u32 flags)
511{ 297{
512 struct ar5416_desc *ads = AR5416DESC(ds); 298 struct ar5416_desc *ads = AR5416DESC(ds);
513 299
@@ -539,14 +325,13 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
539 ads->ds_ctl11 = 0; 325 ads->ds_ctl11 = 0;
540 } 326 }
541} 327}
542EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); 328
543 329static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
544void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, 330 void *lastds,
545 struct ath_desc *lastds, 331 u32 durUpdateEn, u32 rtsctsRate,
546 u32 durUpdateEn, u32 rtsctsRate, 332 u32 rtsctsDuration,
547 u32 rtsctsDuration, 333 struct ath9k_11n_rate_series series[],
548 struct ath9k_11n_rate_series series[], 334 u32 nseries, u32 flags)
549 u32 nseries, u32 flags)
550{ 335{
551 struct ar5416_desc *ads = AR5416DESC(ds); 336 struct ar5416_desc *ads = AR5416DESC(ds);
552 struct ar5416_desc *last_ads = AR5416DESC(lastds); 337 struct ar5416_desc *last_ads = AR5416DESC(lastds);
@@ -595,10 +380,9 @@ void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
595 last_ads->ds_ctl2 = ads->ds_ctl2; 380 last_ads->ds_ctl2 = ads->ds_ctl2;
596 last_ads->ds_ctl3 = ads->ds_ctl3; 381 last_ads->ds_ctl3 = ads->ds_ctl3;
597} 382}
598EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario);
599 383
600void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, 384static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
601 u32 aggrLen) 385 u32 aggrLen)
602{ 386{
603 struct ar5416_desc *ads = AR5416DESC(ds); 387 struct ar5416_desc *ads = AR5416DESC(ds);
604 388
@@ -606,10 +390,9 @@ void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
606 ads->ds_ctl6 &= ~AR_AggrLen; 390 ads->ds_ctl6 &= ~AR_AggrLen;
607 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); 391 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
608} 392}
609EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first);
610 393
611void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, 394static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
612 u32 numDelims) 395 u32 numDelims)
613{ 396{
614 struct ar5416_desc *ads = AR5416DESC(ds); 397 struct ar5416_desc *ads = AR5416DESC(ds);
615 unsigned int ctl6; 398 unsigned int ctl6;
@@ -621,9 +404,8 @@ void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
621 ctl6 |= SM(numDelims, AR_PadDelim); 404 ctl6 |= SM(numDelims, AR_PadDelim);
622 ads->ds_ctl6 = ctl6; 405 ads->ds_ctl6 = ctl6;
623} 406}
624EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle);
625 407
626void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) 408static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
627{ 409{
628 struct ar5416_desc *ads = AR5416DESC(ds); 410 struct ar5416_desc *ads = AR5416DESC(ds);
629 411
@@ -631,28 +413,25 @@ void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
631 ads->ds_ctl1 &= ~AR_MoreAggr; 413 ads->ds_ctl1 &= ~AR_MoreAggr;
632 ads->ds_ctl6 &= ~AR_PadDelim; 414 ads->ds_ctl6 &= ~AR_PadDelim;
633} 415}
634EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last);
635 416
636void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) 417static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
637{ 418{
638 struct ar5416_desc *ads = AR5416DESC(ds); 419 struct ar5416_desc *ads = AR5416DESC(ds);
639 420
640 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); 421 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
641} 422}
642EXPORT_SYMBOL(ath9k_hw_clr11n_aggr);
643 423
644void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, 424static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
645 u32 burstDuration) 425 u32 burstDuration)
646{ 426{
647 struct ar5416_desc *ads = AR5416DESC(ds); 427 struct ar5416_desc *ads = AR5416DESC(ds);
648 428
649 ads->ds_ctl2 &= ~AR_BurstDur; 429 ads->ds_ctl2 &= ~AR_BurstDur;
650 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); 430 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
651} 431}
652EXPORT_SYMBOL(ath9k_hw_set11n_burstduration);
653 432
654void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, 433static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
655 u32 vmf) 434 u32 vmf)
656{ 435{
657 struct ar5416_desc *ads = AR5416DESC(ds); 436 struct ar5416_desc *ads = AR5416DESC(ds);
658 437
@@ -662,6 +441,229 @@ void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
662 ads->ds_ctl0 &= ~AR_VirtMoreFrag; 441 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
663} 442}
664 443
444void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
445{
446 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
447
448 ops->rx_enable = ar9002_hw_rx_enable;
449 ops->set_desc_link = ar9002_hw_set_desc_link;
450 ops->get_desc_link = ar9002_hw_get_desc_link;
451 ops->get_isr = ar9002_hw_get_isr;
452 ops->fill_txdesc = ar9002_hw_fill_txdesc;
453 ops->proc_txdesc = ar9002_hw_proc_txdesc;
454 ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
455 ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
456 ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
457 ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
458 ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
459 ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
460 ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
461 ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag;
462}
463
464static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
465 struct ath9k_tx_queue_info *qi)
466{
467 ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
468 "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
469 ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
470 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
471 ah->txurn_interrupt_mask);
472
473 REG_WRITE(ah, AR_IMR_S0,
474 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
475 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
476 REG_WRITE(ah, AR_IMR_S1,
477 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
478 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
479
480 ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
481 ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
482 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
483}
484
485u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
486{
487 return REG_READ(ah, AR_QTXDP(q));
488}
489EXPORT_SYMBOL(ath9k_hw_gettxbuf);
490
491void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
492{
493 REG_WRITE(ah, AR_QTXDP(q), txdp);
494}
495EXPORT_SYMBOL(ath9k_hw_puttxbuf);
496
497void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
498{
499 ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE,
500 "Enable TXE on queue: %u\n", q);
501 REG_WRITE(ah, AR_Q_TXE, 1 << q);
502}
503EXPORT_SYMBOL(ath9k_hw_txstart);
504
505void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
506{
507 struct ar5416_desc *ads = AR5416DESC(ds);
508
509 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
510 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
511 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
512 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
513 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
514}
515EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
516
517u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
518{
519 u32 npend;
520
521 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
522 if (npend == 0) {
523
524 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
525 npend = 1;
526 }
527
528 return npend;
529}
530EXPORT_SYMBOL(ath9k_hw_numtxpending);
531
532/**
533 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
534 *
535 * @ah: atheros hardware struct
536 * @bIncTrigLevel: whether or not the frame trigger level should be updated
537 *
538 * The frame trigger level specifies the minimum number of bytes,
539 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
540 * before the PCU will initiate sending the frame on the air. This can
541 * mean we initiate transmit before a full frame is on the PCU TX FIFO.
542 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
543 * first)
544 *
545 * Caution must be taken to ensure to set the frame trigger level based
546 * on the DMA request size. For example if the DMA request size is set to
547 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
548 * there need to be enough space in the tx FIFO for the requested transfer
549 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
550 * the threshold to a value beyond 6, then the transmit will hang.
551 *
552 * Current dual stream devices have a PCU TX FIFO size of 8 KB.
553 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
554 * there is a hardware issue which forces us to use 2 KB instead so the
555 * frame trigger level must not exceed 2 KB for these chipsets.
556 */
557bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
558{
559 u32 txcfg, curLevel, newLevel;
560 enum ath9k_int omask;
561
562 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
563 return false;
564
565 omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
566
567 txcfg = REG_READ(ah, AR_TXCFG);
568 curLevel = MS(txcfg, AR_FTRIG);
569 newLevel = curLevel;
570 if (bIncTrigLevel) {
571 if (curLevel < ah->config.max_txtrig_level)
572 newLevel++;
573 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
574 newLevel--;
575 if (newLevel != curLevel)
576 REG_WRITE(ah, AR_TXCFG,
577 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
578
579 ath9k_hw_set_interrupts(ah, omask);
580
581 ah->tx_trig_level = newLevel;
582
583 return newLevel != curLevel;
584}
585EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
586
587bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
588{
589#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
590#define ATH9K_TIME_QUANTUM 100 /* usec */
591 struct ath_common *common = ath9k_hw_common(ah);
592 struct ath9k_hw_capabilities *pCap = &ah->caps;
593 struct ath9k_tx_queue_info *qi;
594 u32 tsfLow, j, wait;
595 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
596
597 if (q >= pCap->total_queues) {
598 ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
599 "invalid queue: %u\n", q);
600 return false;
601 }
602
603 qi = &ah->txq[q];
604 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
605 ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
606 "inactive queue: %u\n", q);
607 return false;
608 }
609
610 REG_WRITE(ah, AR_Q_TXD, 1 << q);
611
612 for (wait = wait_time; wait != 0; wait--) {
613 if (ath9k_hw_numtxpending(ah, q) == 0)
614 break;
615 udelay(ATH9K_TIME_QUANTUM);
616 }
617
618 if (ath9k_hw_numtxpending(ah, q)) {
619 ath_print(common, ATH_DBG_QUEUE,
620 "%s: Num of pending TX Frames %d on Q %d\n",
621 __func__, ath9k_hw_numtxpending(ah, q), q);
622
623 for (j = 0; j < 2; j++) {
624 tsfLow = REG_READ(ah, AR_TSF_L32);
625 REG_WRITE(ah, AR_QUIET2,
626 SM(10, AR_QUIET2_QUIET_DUR));
627 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
628 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
629 REG_SET_BIT(ah, AR_TIMER_MODE,
630 AR_QUIET_TIMER_EN);
631
632 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
633 break;
634
635 ath_print(common, ATH_DBG_QUEUE,
636 "TSF has moved while trying to set "
637 "quiet time TSF: 0x%08x\n", tsfLow);
638 }
639
640 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
641
642 udelay(200);
643 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
644
645 wait = wait_time;
646 while (ath9k_hw_numtxpending(ah, q)) {
647 if ((--wait) == 0) {
648 ath_print(common, ATH_DBG_FATAL,
649 "Failed to stop TX DMA in 100 "
650 "msec after killing last frame\n");
651 break;
652 }
653 udelay(ATH9K_TIME_QUANTUM);
654 }
655
656 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
657 }
658
659 REG_WRITE(ah, AR_Q_TXD, 0);
660 return wait != 0;
661
662#undef ATH9K_TX_STOP_DMA_TIMEOUT
663#undef ATH9K_TIME_QUANTUM
664}
665EXPORT_SYMBOL(ath9k_hw_stoptxdma);
666
665void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) 667void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
666{ 668{
667 *txqs &= ah->intr_txqs; 669 *txqs &= ah->intr_txqs;