Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 278430
b: refs/heads/master
c: 7ff7c82
h: refs/heads/master
v: v3
  • Loading branch information
Nick Kossifidis authored and John W. Linville committed Nov 28, 2011
1 parent 15e3e74 commit 05d30a6
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 94 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 61c0d48f1565efdbab1e913c3cfda997e6299c41
refs/heads/master: 7ff7c82ee4339af277cface9071f81c5c10a9283
8 changes: 7 additions & 1 deletion trunk/drivers/net/wireless/ath/ath5k/ath5k.h
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,13 @@ struct ath5k_hw {
u32 ah_txq_imr_cbrurn;
u32 ah_txq_imr_qtrig;
u32 ah_txq_imr_nofrm;
u32 ah_txq_isr;

u32 ah_txq_isr_txok_all;
u32 ah_txq_isr_txurn;
u32 ah_txq_isr_qcborn;
u32 ah_txq_isr_qcburn;
u32 ah_txq_isr_qtrig;

u32 *ah_rf_banks;
size_t ah_rf_banks_size;
size_t ah_rf_regs_count;
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/ath/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1689,7 +1689,7 @@ ath5k_tasklet_tx(unsigned long data)
struct ath5k_hw *ah = (void *)data;

for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)
if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i)))
if (ah->txqs[i].setup && (ah->ah_txq_isr_txok_all & BIT(i)))
ath5k_tx_processq(ah, &ah->txqs[i]);

ah->tx_pending = false;
Expand Down
245 changes: 160 additions & 85 deletions trunk/drivers/net/wireless/ath/ath5k/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,6 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
*
* XXX: Link this with tx DMA size ?
* XXX: Use it to save interrupts ?
* TODO: Needs testing, i think it's related to bmiss...
*/
int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
{
Expand Down Expand Up @@ -523,62 +522,161 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
* being mapped on some standard non hw-specific positions
* (check out &ath5k_int).
*
* NOTE: We use read-and-clear register, so after this function is called ISR
* is zeroed.
* NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this
* function gets called are cleared on return.
*/
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
{
u32 data;
u32 data = 0;

/*
* Read interrupt status from the Interrupt Status register
* on 5210
* Read interrupt status from Primary Interrupt
* Register.
*
* Note: PISR/SISR Not available on 5210
*/
if (ah->ah_version == AR5K_AR5210) {
data = ath5k_hw_reg_read(ah, AR5K_ISR);
if (unlikely(data == AR5K_INT_NOCARD)) {
*interrupt_mask = data;
u32 isr = 0;
isr = ath5k_hw_reg_read(ah, AR5K_ISR);
if (unlikely(isr == AR5K_INT_NOCARD)) {
*interrupt_mask = isr;
return -ENODEV;
}
} else {

/*
* Read interrupt status from Interrupt
* Status Register shadow copy (Read And Clear)
*
* Note: PISR/SISR Not available on 5210
* Filter out the non-common bits from the interrupt
* status.
*/
data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
if (unlikely(data == AR5K_INT_NOCARD)) {
*interrupt_mask = data;
*interrupt_mask = (isr & AR5K_INT_COMMON) & ah->ah_imr;

/* Hanlde INT_FATAL */
if (unlikely(isr & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
| AR5K_ISR_DPERR)))
*interrupt_mask |= AR5K_INT_FATAL;

/*
* XXX: BMISS interrupts may occur after association.
* I found this on 5210 code but it needs testing. If this is
* true we should disable them before assoc and re-enable them
* after a successful assoc + some jiffies.
interrupt_mask &= ~AR5K_INT_BMISS;
*/

data = isr;
} else {
u32 pisr = 0;
u32 pisr_clear = 0;
u32 sisr0 = 0;
u32 sisr1 = 0;
u32 sisr2 = 0;
u32 sisr3 = 0;
u32 sisr4 = 0;

/* Read PISR and SISRs... */
pisr = ath5k_hw_reg_read(ah, AR5K_PISR);
if (unlikely(pisr == AR5K_INT_NOCARD)) {
*interrupt_mask = pisr;
return -ENODEV;
}
}

/*
* Get abstract interrupt mask (driver-compatible)
*/
*interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
sisr0 = ath5k_hw_reg_read(ah, AR5K_SISR0);
sisr1 = ath5k_hw_reg_read(ah, AR5K_SISR1);
sisr2 = ath5k_hw_reg_read(ah, AR5K_SISR2);
sisr3 = ath5k_hw_reg_read(ah, AR5K_SISR3);
sisr4 = ath5k_hw_reg_read(ah, AR5K_SISR4);

if (ah->ah_version != AR5K_AR5210) {
u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
/*
* PISR holds the logical OR of interrupt bits
* from SISR registers:
*
* TXOK and TXDESC -> Logical OR of TXOK and TXDESC
* per-queue bits on SISR0
*
* TXERR and TXEOL -> Logical OR of TXERR and TXEOL
* per-queue bits on SISR1
*
* TXURN -> Logical OR of TXURN per-queue bits on SISR2
*
* HIUERR -> Logical OR of MCABT, SSERR and DPER bits on SISR2
*
* BCNMISC -> Logical OR of TIM, CAB_END, DTIM_SYNC
* BCN_TIMEOUT, CAB_TIMEOUT and DTIM
* (and TSFOOR ?) bits on SISR2
*
* QCBRORN and QCBRURN -> Logical OR of QCBRORN and
* QCBRURN per-queue bits on SISR3
* QTRIG -> Logical OR of QTRIG per-queue bits on SISR4
*
* If we clean these bits on PISR we 'll also clear all
* related bits from SISRs, e.g. if we write the TXOK bit on
* PISR we 'll clean all TXOK bits from SISR0 so if a new TXOK
* interrupt got fired for another queue while we were reading
* the interrupt registers and we write back the TXOK bit on
* PISR we 'll lose it. So make sure that we don't write back
* on PISR any bits that come from SISRs. Clearing them from
* SISRs will also clear PISR so no need to worry here.
*/

/*HIU = Host Interface Unit (PCI etc)*/
if (unlikely(data & (AR5K_ISR_HIUERR)))
*interrupt_mask |= AR5K_INT_FATAL;
pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS;

/*Beacon Not Ready*/
if (unlikely(data & (AR5K_ISR_BNR)))
*interrupt_mask |= AR5K_INT_BNR;
/*
* Write to clear them...
* Note: This means that each bit we write back
* to the registers will get cleared, leaving the
* rest unaffected. So this won't affect new interrupts
* we didn't catch while reading/processing, we 'll get
* them next time get_isr gets called.
*/
ath5k_hw_reg_write(ah, sisr0, AR5K_SISR0);
ath5k_hw_reg_write(ah, sisr1, AR5K_SISR1);
ath5k_hw_reg_write(ah, sisr2, AR5K_SISR2);
ath5k_hw_reg_write(ah, sisr3, AR5K_SISR3);
ath5k_hw_reg_write(ah, sisr4, AR5K_SISR4);
ath5k_hw_reg_write(ah, pisr_clear, AR5K_PISR);
/* Flush previous write */
ath5k_hw_reg_read(ah, AR5K_PISR);

if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
AR5K_SISR2_DPERR |
AR5K_SISR2_MCABT)))
*interrupt_mask |= AR5K_INT_FATAL;
/*
* Filter out the non-common bits from the interrupt
* status.
*/
*interrupt_mask = (pisr & AR5K_INT_COMMON) & ah->ah_imr;


/* We treat TXOK,TXDESC, TXERR and TXEOL
* the same way (schedule the tx tasklet)
* so we track them all together per queue */
if (pisr & AR5K_ISR_TXOK)
ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0,
AR5K_SISR0_QCU_TXOK);

if (pisr & AR5K_ISR_TXDESC)
ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0,
AR5K_SISR0_QCU_TXDESC);

if (data & AR5K_ISR_TIM)
if (pisr & AR5K_ISR_TXERR)
ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1,
AR5K_SISR1_QCU_TXERR);

if (pisr & AR5K_ISR_TXEOL)
ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1,
AR5K_SISR1_QCU_TXEOL);

/* Currently this is not much usefull since we treat
* all queues the same way if we get a TXURN (update
* tx trigger level) but we might need it later on*/
if (pisr & AR5K_ISR_TXURN)
ah->ah_txq_isr_txurn |= AR5K_REG_MS(sisr2,
AR5K_SISR2_QCU_TXURN);

/* Misc Beacon related interrupts */

/* For AR5211 */
if (pisr & AR5K_ISR_TIM)
*interrupt_mask |= AR5K_INT_TIM;

if (data & AR5K_ISR_BCNMISC) {
/* For AR5212+ */
if (pisr & AR5K_ISR_BCNMISC) {
if (sisr2 & AR5K_SISR2_TIM)
*interrupt_mask |= AR5K_INT_TIM;
if (sisr2 & AR5K_SISR2_DTIM)
Expand All @@ -591,63 +689,40 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
*interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
}

if (data & AR5K_ISR_RXDOPPLER)
/* Below interrupts are unlikely to happen */

/* HIU = Host Interface Unit (PCI etc)
* Can be one of MCABT, SSERR, DPERR from SISR2 */
if (unlikely(pisr & (AR5K_ISR_HIUERR)))
*interrupt_mask |= AR5K_INT_FATAL;


/*Beacon Not Ready*/
if (unlikely(pisr & (AR5K_ISR_BNR)))
*interrupt_mask |= AR5K_INT_BNR;

if (unlikely(pisr & (AR5K_ISR_RXDOPPLER)))
*interrupt_mask |= AR5K_INT_RX_DOPPLER;
if (data & AR5K_ISR_QCBRORN) {

if (unlikely(pisr & (AR5K_ISR_QCBRORN))) {
*interrupt_mask |= AR5K_INT_QCBRORN;
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
AR5K_SISR3_QCBRORN);
ah->ah_txq_isr_qcborn |= AR5K_REG_MS(sisr3,
AR5K_SISR3_QCBRORN);
}
if (data & AR5K_ISR_QCBRURN) {

if (unlikely(pisr & (AR5K_ISR_QCBRURN))) {
*interrupt_mask |= AR5K_INT_QCBRURN;
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
AR5K_SISR3_QCBRURN);
ah->ah_txq_isr_qcburn |= AR5K_REG_MS(sisr3,
AR5K_SISR3_QCBRURN);
}
if (data & AR5K_ISR_QTRIG) {

if (unlikely(pisr & (AR5K_ISR_QTRIG))) {
*interrupt_mask |= AR5K_INT_QTRIG;
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
AR5K_SISR4_QTRIG);
ah->ah_txq_isr_qtrig |= AR5K_REG_MS(sisr4,
AR5K_SISR4_QTRIG);
}

if (data & AR5K_ISR_TXOK)
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
AR5K_SISR0_QCU_TXOK);

if (data & AR5K_ISR_TXDESC)
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
AR5K_SISR0_QCU_TXDESC);

if (data & AR5K_ISR_TXERR)
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
AR5K_SISR1_QCU_TXERR);

if (data & AR5K_ISR_TXEOL)
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
AR5K_SISR1_QCU_TXEOL);

if (data & AR5K_ISR_TXURN)
ah->ah_txq_isr |= AR5K_REG_MS(
ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
AR5K_SISR2_QCU_TXURN);
} else {
if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
| AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
*interrupt_mask |= AR5K_INT_FATAL;

/*
* XXX: BMISS interrupts may occur after association.
* I found this on 5210 code but it needs testing. If this is
* true we should disable them before assoc and re-enable them
* after a successful assoc + some jiffies.
interrupt_mask &= ~AR5K_INT_BMISS;
*/
data = pisr;
}

/*
Expand Down
27 changes: 21 additions & 6 deletions trunk/drivers/net/wireless/ath/ath5k/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@
* 5211/5212 we have one primary and 4 secondary registers.
* So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
* Most of these bits are common for all chipsets.
*
* NOTE: On 5211+ TXOK, TXDESC, TXERR, TXEOL and TXURN contain
* the logical OR from per-queue interrupt bits found on SISR registers
* (see below).
*/
#define AR5K_ISR 0x001c /* Register Address [5210] */
#define AR5K_PISR 0x0080 /* Register Address [5211+] */
Expand All @@ -292,7 +296,10 @@
#define AR5K_ISR_TXOK 0x00000040 /* Frame successfully transmitted */
#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) */
#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout)
* NOTE: We don't have per-queue info for this
* one, but we can enable it per-queue through
* TXNOFRM_QCU field on TXNOFRM register */
#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
Expand All @@ -302,21 +309,29 @@
#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+]
* 'or' of MCABT, SSERR, DPERR from SISR2 */
#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */
#define AR5K_ISR_DPERR 0x00400000 /* Bus parity error [5210] */
#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
#define AR5K_ISR_TIM 0x00800000 /* [5211+] */
#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
#define AR5K_ISR_BCNMISC 0x00800000 /* Misc beacon related interrupt
* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
* CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */
#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */
#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */
#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */

#define AR5K_ISR_BITS_FROM_SISRS (AR5K_ISR_TXOK | AR5K_ISR_TXDESC |\
AR5K_ISR_TXERR | AR5K_ISR_TXEOL |\
AR5K_ISR_TXURN | AR5K_ISR_HIUERR |\
AR5K_ISR_BCNMISC | AR5K_ISR_QCBRORN |\
AR5K_ISR_QCBRURN | AR5K_ISR_QTRIG)

/*
* Secondary status registers [5211+] (0 - 4)
*
Expand Down Expand Up @@ -347,7 +362,7 @@
#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */
#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF Out of range */

#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
Expand Down

0 comments on commit 05d30a6

Please sign in to comment.