aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath5k/ath5k.h86
-rw-r--r--drivers/net/wireless/ath5k/base.c7
-rw-r--r--drivers/net/wireless/ath5k/dma.c190
-rw-r--r--drivers/net/wireless/ath5k/qcu.c37
-rw-r--r--drivers/net/wireless/ath5k/reg.h3
-rw-r--r--drivers/net/wireless/ath5k/reset.c3
6 files changed, 247 insertions, 79 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 53ea439aff4..b1179203991 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -507,11 +507,15 @@ enum ath5k_tx_queue_id {
507#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */ 507#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
508#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */ 508#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
509#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */ 509#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
510#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0020 /* Disable random post-backoff */ 510#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */
511#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0040 /* Enable ready time expiry policy (?)*/ 511#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */
512#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0080 /* Enable backoff while bursting */ 512#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */
513#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x0100 /* Disable backoff while bursting */ 513#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */
514#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x0200 /* Enable hw compression -not implemented-*/ 514#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */
515#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/
516#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */
517#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */
518#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
515 519
516/* 520/*
517 * A struct to hold tx queue's parameters 521 * A struct to hold tx queue's parameters
@@ -853,7 +857,7 @@ enum ath5k_ant_setting {
853 * checked. We should do this with ath5k_hw_update_mib_counters() but 857 * checked. We should do this with ath5k_hw_update_mib_counters() but
854 * it seems we should also then do some noise immunity work. 858 * it seems we should also then do some noise immunity work.
855 * @AR5K_INT_RXPHY: RX PHY Error 859 * @AR5K_INT_RXPHY: RX PHY Error
856 * @AR5K_INT_RXKCM: ?? 860 * @AR5K_INT_RXKCM: RX Key cache miss
857 * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a 861 * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
858 * beacon that must be handled in software. The alternative is if you 862 * beacon that must be handled in software. The alternative is if you
859 * have VEOL support, in that case you let the hardware deal with things. 863 * have VEOL support, in that case you let the hardware deal with things.
@@ -869,7 +873,7 @@ enum ath5k_ant_setting {
869 * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA 873 * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
870 * errors. These types of errors we can enable seem to be of type 874 * errors. These types of errors we can enable seem to be of type
871 * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. 875 * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
872 * @AR5K_INT_GLOBAL: Seems to be used to clear and set the IER 876 * @AR5K_INT_GLOBAL: Used to clear and set the IER
873 * @AR5K_INT_NOCARD: signals the card has been removed 877 * @AR5K_INT_NOCARD: signals the card has been removed
874 * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same 878 * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
875 * bit value 879 * bit value
@@ -881,36 +885,61 @@ enum ath5k_ant_setting {
881 * MACs. 885 * MACs.
882 */ 886 */
883enum ath5k_int { 887enum ath5k_int {
884 AR5K_INT_RX = 0x00000001, /* Not common */ 888 AR5K_INT_RXOK = 0x00000001,
885 AR5K_INT_RXDESC = 0x00000002, 889 AR5K_INT_RXDESC = 0x00000002,
890 AR5K_INT_RXERR = 0x00000004,
886 AR5K_INT_RXNOFRM = 0x00000008, 891 AR5K_INT_RXNOFRM = 0x00000008,
887 AR5K_INT_RXEOL = 0x00000010, 892 AR5K_INT_RXEOL = 0x00000010,
888 AR5K_INT_RXORN = 0x00000020, 893 AR5K_INT_RXORN = 0x00000020,
889 AR5K_INT_TX = 0x00000040, /* Not common */ 894 AR5K_INT_TXOK = 0x00000040,
890 AR5K_INT_TXDESC = 0x00000080, 895 AR5K_INT_TXDESC = 0x00000080,
896 AR5K_INT_TXERR = 0x00000100,
897 AR5K_INT_TXNOFRM = 0x00000200,
898 AR5K_INT_TXEOL = 0x00000400,
891 AR5K_INT_TXURN = 0x00000800, 899 AR5K_INT_TXURN = 0x00000800,
892 AR5K_INT_MIB = 0x00001000, 900 AR5K_INT_MIB = 0x00001000,
901 AR5K_INT_SWI = 0x00002000,
893 AR5K_INT_RXPHY = 0x00004000, 902 AR5K_INT_RXPHY = 0x00004000,
894 AR5K_INT_RXKCM = 0x00008000, 903 AR5K_INT_RXKCM = 0x00008000,
895 AR5K_INT_SWBA = 0x00010000, 904 AR5K_INT_SWBA = 0x00010000,
905 AR5K_INT_BRSSI = 0x00020000,
896 AR5K_INT_BMISS = 0x00040000, 906 AR5K_INT_BMISS = 0x00040000,
897 AR5K_INT_BNR = 0x00100000, /* Not common */ 907 AR5K_INT_FATAL = 0x00080000, /* Non common */
898 AR5K_INT_GPIO = 0x01000000, 908 AR5K_INT_BNR = 0x00100000, /* Non common */
899 AR5K_INT_FATAL = 0x40000000, /* Not common */ 909 AR5K_INT_TIM = 0x00200000, /* Non common */
900 AR5K_INT_GLOBAL = 0x80000000, 910 AR5K_INT_DTIM = 0x00400000, /* Non common */
901 911 AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */
902 AR5K_INT_COMMON = AR5K_INT_RXNOFRM 912 AR5K_INT_GPIO = 0x01000000,
903 | AR5K_INT_RXDESC 913 AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */
904 | AR5K_INT_RXEOL 914 AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */
905 | AR5K_INT_RXORN 915 AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */
906 | AR5K_INT_TXURN 916 AR5K_INT_QCBRORN = 0x10000000, /* Non common */
907 | AR5K_INT_TXDESC 917 AR5K_INT_QCBRURN = 0x20000000, /* Non common */
908 | AR5K_INT_MIB 918 AR5K_INT_QTRIG = 0x40000000, /* Non common */
909 | AR5K_INT_RXPHY 919 AR5K_INT_GLOBAL = 0x80000000,
910 | AR5K_INT_RXKCM 920
911 | AR5K_INT_SWBA 921 AR5K_INT_COMMON = AR5K_INT_RXOK
912 | AR5K_INT_BMISS 922 | AR5K_INT_RXDESC
913 | AR5K_INT_GPIO, 923 | AR5K_INT_RXERR
924 | AR5K_INT_RXNOFRM
925 | AR5K_INT_RXEOL
926 | AR5K_INT_RXORN
927 | AR5K_INT_TXOK
928 | AR5K_INT_TXDESC
929 | AR5K_INT_TXERR
930 | AR5K_INT_TXNOFRM
931 | AR5K_INT_TXEOL
932 | AR5K_INT_TXURN
933 | AR5K_INT_MIB
934 | AR5K_INT_SWI
935 | AR5K_INT_RXPHY
936 | AR5K_INT_RXKCM
937 | AR5K_INT_SWBA
938 | AR5K_INT_BRSSI
939 | AR5K_INT_BMISS
940 | AR5K_INT_GPIO
941 | AR5K_INT_GLOBAL,
942
914 AR5K_INT_NOCARD = 0xffffffff 943 AR5K_INT_NOCARD = 0xffffffff
915}; 944};
916 945
@@ -1081,6 +1110,11 @@ struct ath5k_hw {
1081 u32 ah_txq_imr_txurn; 1110 u32 ah_txq_imr_txurn;
1082 u32 ah_txq_imr_txdesc; 1111 u32 ah_txq_imr_txdesc;
1083 u32 ah_txq_imr_txeol; 1112 u32 ah_txq_imr_txeol;
1113 u32 ah_txq_imr_cbrorn;
1114 u32 ah_txq_imr_cbrurn;
1115 u32 ah_txq_imr_qtrig;
1116 u32 ah_txq_imr_nofrm;
1117 u32 ah_txq_isr;
1084 u32 *ah_rf_banks; 1118 u32 *ah_rf_banks;
1085 size_t ah_rf_banks_size; 1119 size_t ah_rf_banks_size;
1086 struct ath5k_gain ah_gain; 1120 struct ath5k_gain ah_gain;
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 6caabebc4c6..7ac5f2847da 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -2216,7 +2216,7 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
2216 */ 2216 */
2217 sc->curchan = sc->hw->conf.channel; 2217 sc->curchan = sc->hw->conf.channel;
2218 sc->curband = &sc->sbands[sc->curchan->band]; 2218 sc->curband = &sc->sbands[sc->curchan->band];
2219 sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL | 2219 sc->imask = AR5K_INT_RXOK | AR5K_INT_TXOK | AR5K_INT_RXEOL |
2220 AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL | 2220 AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
2221 AR5K_INT_MIB; 2221 AR5K_INT_MIB;
2222 ret = ath5k_reset(sc, false, false); 2222 ret = ath5k_reset(sc, false, false);
@@ -2410,9 +2410,10 @@ ath5k_intr(int irq, void *dev_id)
2410 /* bump tx trigger level */ 2410 /* bump tx trigger level */
2411 ath5k_hw_update_tx_triglevel(ah, true); 2411 ath5k_hw_update_tx_triglevel(ah, true);
2412 } 2412 }
2413 if (status & AR5K_INT_RX) 2413 if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
2414 tasklet_schedule(&sc->rxtq); 2414 tasklet_schedule(&sc->rxtq);
2415 if (status & AR5K_INT_TX) 2415 if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
2416 | AR5K_INT_TXERR | AR5K_INT_TXEOL))
2416 tasklet_schedule(&sc->txtq); 2417 tasklet_schedule(&sc->txtq);
2417 if (status & AR5K_INT_BMISS) { 2418 if (status & AR5K_INT_BMISS) {
2418 } 2419 }
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c
index 7adceb2c7fa..7e2b1a67e5d 100644
--- a/drivers/net/wireless/ath5k/dma.c
+++ b/drivers/net/wireless/ath5k/dma.c
@@ -472,9 +472,6 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
472 * 472 *
473 * NOTE: We use read-and-clear register, so after this function is called ISR 473 * NOTE: We use read-and-clear register, so after this function is called ISR
474 * is zeroed. 474 * is zeroed.
475 *
476 * XXX: Why filter interrupts in sw with interrupt_mask ? No benefit at all
477 * plus it can be misleading (one might thing that we save interrupts this way)
478 */ 475 */
479int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) 476int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
480{ 477{
@@ -494,11 +491,16 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
494 } 491 }
495 } else { 492 } else {
496 /* 493 /*
497 * Read interrupt status from the Read-And-Clear 494 * Read interrupt status from Interrupt
498 * shadow register. 495 * Status Register shadow copy (Read And Clear)
496 *
499 * Note: PISR/SISR Not available on 5210 497 * Note: PISR/SISR Not available on 5210
500 */ 498 */
501 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); 499 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
500 if (unlikely(data == AR5K_INT_NOCARD)) {
501 *interrupt_mask = data;
502 return -ENODEV;
503 }
502 } 504 }
503 505
504 /* 506 /*
@@ -506,17 +508,9 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
506 */ 508 */
507 *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; 509 *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
508 510
509 if (unlikely(data == AR5K_INT_NOCARD))
510 return -ENODEV;
511
512 if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
513 *interrupt_mask |= AR5K_INT_RX;
514
515 if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
516 | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
517 *interrupt_mask |= AR5K_INT_TX;
518
519 if (ah->ah_version != AR5K_AR5210) { 511 if (ah->ah_version != AR5K_AR5210) {
512 u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
513
520 /*HIU = Host Interface Unit (PCI etc)*/ 514 /*HIU = Host Interface Unit (PCI etc)*/
521 if (unlikely(data & (AR5K_ISR_HIUERR))) 515 if (unlikely(data & (AR5K_ISR_HIUERR)))
522 *interrupt_mask |= AR5K_INT_FATAL; 516 *interrupt_mask |= AR5K_INT_FATAL;
@@ -524,24 +518,93 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
524 /*Beacon Not Ready*/ 518 /*Beacon Not Ready*/
525 if (unlikely(data & (AR5K_ISR_BNR))) 519 if (unlikely(data & (AR5K_ISR_BNR)))
526 *interrupt_mask |= AR5K_INT_BNR; 520 *interrupt_mask |= AR5K_INT_BNR;
527 }
528 521
529 /* 522 if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
530 * XXX: BMISS interrupts may occur after association. 523 AR5K_SISR2_DPERR |
531 * I found this on 5210 code but it needs testing. If this is 524 AR5K_SISR2_MCABT)))
532 * true we should disable them before assoc and re-enable them 525 *interrupt_mask |= AR5K_INT_FATAL;
533 * after a successfull assoc + some jiffies. 526
534 */ 527 if (data & AR5K_ISR_TIM)
535#if 0 528 *interrupt_mask |= AR5K_INT_TIM;
536 interrupt_mask &= ~AR5K_INT_BMISS; 529
537#endif 530 if (data & AR5K_ISR_BCNMISC) {
531 if (sisr2 & AR5K_SISR2_TIM)
532 *interrupt_mask |= AR5K_INT_TIM;
533 if (sisr2 & AR5K_SISR2_DTIM)
534 *interrupt_mask |= AR5K_INT_DTIM;
535 if (sisr2 & AR5K_SISR2_DTIM_SYNC)
536 *interrupt_mask |= AR5K_INT_DTIM_SYNC;
537 if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
538 *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
539 if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
540 *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
541 }
542
543 if (data & AR5K_ISR_RXDOPPLER)
544 *interrupt_mask |= AR5K_INT_RX_DOPPLER;
545 if (data & AR5K_ISR_QCBRORN) {
546 *interrupt_mask |= AR5K_INT_QCBRORN;
547 ah->ah_txq_isr |= AR5K_REG_MS(
548 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
549 AR5K_SISR3_QCBRORN);
550 }
551 if (data & AR5K_ISR_QCBRURN) {
552 *interrupt_mask |= AR5K_INT_QCBRURN;
553 ah->ah_txq_isr |= AR5K_REG_MS(
554 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
555 AR5K_SISR3_QCBRURN);
556 }
557 if (data & AR5K_ISR_QTRIG) {
558 *interrupt_mask |= AR5K_INT_QTRIG;
559 ah->ah_txq_isr |= AR5K_REG_MS(
560 ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
561 AR5K_SISR4_QTRIG);
562 }
563
564 if (data & AR5K_ISR_TXOK)
565 ah->ah_txq_isr |= AR5K_REG_MS(
566 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
567 AR5K_SISR0_QCU_TXOK);
568
569 if (data & AR5K_ISR_TXDESC)
570 ah->ah_txq_isr |= AR5K_REG_MS(
571 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
572 AR5K_SISR0_QCU_TXDESC);
573
574 if (data & AR5K_ISR_TXERR)
575 ah->ah_txq_isr |= AR5K_REG_MS(
576 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
577 AR5K_SISR1_QCU_TXERR);
578
579 if (data & AR5K_ISR_TXEOL)
580 ah->ah_txq_isr |= AR5K_REG_MS(
581 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
582 AR5K_SISR1_QCU_TXEOL);
583
584 if (data & AR5K_ISR_TXURN)
585 ah->ah_txq_isr |= AR5K_REG_MS(
586 ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
587 AR5K_SISR2_QCU_TXURN);
588 } else {
589 if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
590 | AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
591 *interrupt_mask |= AR5K_INT_FATAL;
592
593 /*
594 * XXX: BMISS interrupts may occur after association.
595 * I found this on 5210 code but it needs testing. If this is
596 * true we should disable them before assoc and re-enable them
597 * after a successfull assoc + some jiffies.
598 interrupt_mask &= ~AR5K_INT_BMISS;
599 */
600 }
538 601
539 /* 602 /*
540 * In case we didn't handle anything, 603 * In case we didn't handle anything,
541 * print the register value. 604 * print the register value.
542 */ 605 */
543 if (unlikely(*interrupt_mask == 0 && net_ratelimit())) 606 if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
544 ATH5K_PRINTF("0x%08x\n", data); 607 ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
545 608
546 return 0; 609 return 0;
547} 610}
@@ -560,14 +623,17 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
560{ 623{
561 enum ath5k_int old_mask, int_mask; 624 enum ath5k_int old_mask, int_mask;
562 625
626 old_mask = ah->ah_imr;
627
563 /* 628 /*
564 * Disable card interrupts to prevent any race conditions 629 * Disable card interrupts to prevent any race conditions
565 * (they will be re-enabled afterwards). 630 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
631 * is set again on the new mask).
566 */ 632 */
567 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); 633 if (old_mask & AR5K_INT_GLOBAL) {
568 ath5k_hw_reg_read(ah, AR5K_IER); 634 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
569 635 ath5k_hw_reg_read(ah, AR5K_IER);
570 old_mask = ah->ah_imr; 636 }
571 637
572 /* 638 /*
573 * Add additional, chipset-dependent interrupt mask flags 639 * Add additional, chipset-dependent interrupt mask flags
@@ -575,30 +641,64 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
575 */ 641 */
576 int_mask = new_mask & AR5K_INT_COMMON; 642 int_mask = new_mask & AR5K_INT_COMMON;
577 643
578 if (new_mask & AR5K_INT_RX)
579 int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
580 AR5K_IMR_RXDESC;
581
582 if (new_mask & AR5K_INT_TX)
583 int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
584 AR5K_IMR_TXURN;
585
586 if (ah->ah_version != AR5K_AR5210) { 644 if (ah->ah_version != AR5K_AR5210) {
645 /* Preserve per queue TXURN interrupt mask */
646 u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
647 & AR5K_SIMR2_QCU_TXURN;
648
587 if (new_mask & AR5K_INT_FATAL) { 649 if (new_mask & AR5K_INT_FATAL) {
588 int_mask |= AR5K_IMR_HIUERR; 650 int_mask |= AR5K_IMR_HIUERR;
589 AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT | 651 simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
590 AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR); 652 | AR5K_SIMR2_DPERR);
591 } 653 }
654
655 /*Beacon Not Ready*/
656 if (new_mask & AR5K_INT_BNR)
657 int_mask |= AR5K_INT_BNR;
658
659 if (new_mask & AR5K_INT_TIM)
660 int_mask |= AR5K_IMR_TIM;
661
662 if (new_mask & AR5K_INT_TIM)
663 simr2 |= AR5K_SISR2_TIM;
664 if (new_mask & AR5K_INT_DTIM)
665 simr2 |= AR5K_SISR2_DTIM;
666 if (new_mask & AR5K_INT_DTIM_SYNC)
667 simr2 |= AR5K_SISR2_DTIM_SYNC;
668 if (new_mask & AR5K_INT_BCN_TIMEOUT)
669 simr2 |= AR5K_SISR2_BCN_TIMEOUT;
670 if (new_mask & AR5K_INT_CAB_TIMEOUT)
671 simr2 |= AR5K_SISR2_CAB_TIMEOUT;
672
673 if (new_mask & AR5K_INT_RX_DOPPLER)
674 int_mask |= AR5K_IMR_RXDOPPLER;
675
676 /* Note: Per queue interrupt masks
677 * are set via reset_tx_queue (qcu.c) */
678 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
679 ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
680
681 } else {
682 if (new_mask & AR5K_INT_FATAL)
683 int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
684 | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
685
686 ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
592 } 687 }
593 688
594 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); 689 /* If RXNOFRM interrupt is masked disable it
690 * by setting AR5K_RXNOFRM to zero */
691 if (!(new_mask & AR5K_INT_RXNOFRM))
692 ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
595 693
596 /* Store new interrupt mask */ 694 /* Store new interrupt mask */
597 ah->ah_imr = new_mask; 695 ah->ah_imr = new_mask;
598 696
599 /* ..re-enable interrupts */ 697 /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
600 ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); 698 if (new_mask & AR5K_INT_GLOBAL) {
601 ath5k_hw_reg_read(ah, AR5K_IER); 699 ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
700 ath5k_hw_reg_read(ah, AR5K_IER);
701 }
602 702
603 return old_mask; 703 return old_mask;
604} 704}
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c
index 01bf09176d2..1b7bc50ea8e 100644
--- a/drivers/net/wireless/ath5k/qcu.c
+++ b/drivers/net/wireless/ath5k/qcu.c
@@ -432,13 +432,30 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
432 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) 432 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
433 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); 433 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
434 434
435 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
436 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
437
438 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
439 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
440
441 if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
442 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
443
444 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
445 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
435 446
436 /* Update secondary interrupt mask registers */ 447 /* Update secondary interrupt mask registers */
448
449 /* Filter out inactive queues */
437 ah->ah_txq_imr_txok &= ah->ah_txq_status; 450 ah->ah_txq_imr_txok &= ah->ah_txq_status;
438 ah->ah_txq_imr_txerr &= ah->ah_txq_status; 451 ah->ah_txq_imr_txerr &= ah->ah_txq_status;
439 ah->ah_txq_imr_txurn &= ah->ah_txq_status; 452 ah->ah_txq_imr_txurn &= ah->ah_txq_status;
440 ah->ah_txq_imr_txdesc &= ah->ah_txq_status; 453 ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
441 ah->ah_txq_imr_txeol &= ah->ah_txq_status; 454 ah->ah_txq_imr_txeol &= ah->ah_txq_status;
455 ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
456 ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
457 ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
458 ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
442 459
443 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, 460 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
444 AR5K_SIMR0_QCU_TXOK) | 461 AR5K_SIMR0_QCU_TXOK) |
@@ -448,8 +465,24 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
448 AR5K_SIMR1_QCU_TXERR) | 465 AR5K_SIMR1_QCU_TXERR) |
449 AR5K_REG_SM(ah->ah_txq_imr_txeol, 466 AR5K_REG_SM(ah->ah_txq_imr_txeol,
450 AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); 467 AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
451 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn, 468 /* Update simr2 but don't overwrite rest simr2 settings */
452 AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2); 469 AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
470 AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
471 AR5K_REG_SM(ah->ah_txq_imr_txurn,
472 AR5K_SIMR2_QCU_TXURN));
473 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
474 AR5K_SIMR3_QCBRORN) |
475 AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
476 AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
477 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
478 AR5K_SIMR4_QTRIG), AR5K_SIMR4);
479 /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
480 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
481 AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
482 /* No queue has TXNOFRM enabled, disable the interrupt
483 * by setting AR5K_TXNOFRM to zero */
484 if (ah->ah_txq_imr_nofrm == 0)
485 ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
453 } 486 }
454 487
455 return 0; 488 return 0;
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index e557fe178bb..0dae54d00f0 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -234,6 +234,7 @@
234#define AR5K_TXNOFRM 0x004c 234#define AR5K_TXNOFRM 0x004c
235#define AR5K_TXNOFRM_M 0x000003ff 235#define AR5K_TXNOFRM_M 0x000003ff
236#define AR5K_TXNOFRM_QCU 0x000ffc00 236#define AR5K_TXNOFRM_QCU 0x000ffc00
237#define AR5K_TXNOFRM_QCU_S 10
237 238
238/* 239/*
239 * Receive frame gap timeout register 240 * Receive frame gap timeout register
@@ -350,7 +351,7 @@
350 351
351#define AR5K_SISR3 0x0090 /* Register Address [5211+] */ 352#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
352#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ 353#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
353#define AR5K_SISR3_QCBORN_S 0 354#define AR5K_SISR3_QCBRORN_S 0
354#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ 355#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
355#define AR5K_SISR3_QCBRURN_S 16 356#define AR5K_SISR3_QCBRURN_S 16
356 357
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c
index 1b6d45b6772..b51bc030da0 100644
--- a/drivers/net/wireless/ath5k/reset.c
+++ b/drivers/net/wireless/ath5k/reset.c
@@ -864,8 +864,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
864 864
865 /* Pre-enable interrupts on 5211/5212*/ 865 /* Pre-enable interrupts on 5211/5212*/
866 if (ah->ah_version != AR5K_AR5210) 866 if (ah->ah_version != AR5K_AR5210)
867 ath5k_hw_set_imr(ah, AR5K_INT_RX | AR5K_INT_TX | 867 ath5k_hw_set_imr(ah, ah->ah_imr);
868 AR5K_INT_FATAL);
869 868
870 /* 869 /*
871 * Set RF kill flags if supported by the device (read from the EEPROM) 870 * Set RF kill flags if supported by the device (read from the EEPROM)