diff options
Diffstat (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c')
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_main.c | 65 |
1 files changed, 30 insertions, 35 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a85176325e9..12c93d274ae 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1785,10 +1785,6 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); } - /* We get spurious IRQs, althought they are masked. - * Assume they are void and ignore them. - */ - bcmirq_handled(~(bcm->irq_savedstate)); /* IRQ_PIO_WORKAROUND is handled in the top-half. */ bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); #ifdef CONFIG_BCM43XX_DEBUG @@ -1809,41 +1805,31 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_unlock_mmio(bcm, flags); } -static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, - u32 reason, u32 mask) +static void pio_irq_workaround(struct bcm43xx_private *bcm, + u16 base, int queueidx) { - bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) - & 0x0001dc00; - bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) - & 0x0000dc00; - bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) - & 0x0000dc00; - bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) - & 0x0001dc00; + u16 rxctl; + + rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL); + if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE) + bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE; + else + bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE; +} +static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason) +{ if (bcm43xx_using_pio(bcm) && (bcm->current_core->rev < 3) && (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { /* Apply a PIO specific workaround to the dma_reasons */ - -#define apply_pio_workaround(BASE, QNUM) \ - do { \ - if (bcm43xx_read16(bcm, BASE + BCM43xx_PIO_RXCTL) & BCM43xx_PIO_RXCTL_DATAAVAILABLE) \ - bcm->dma_reason[QNUM] |= 0x00010000; \ - else \ - bcm->dma_reason[QNUM] &= ~0x00010000; \ - } while (0) - - apply_pio_workaround(BCM43xx_MMIO_PIO1_BASE, 0); - apply_pio_workaround(BCM43xx_MMIO_PIO2_BASE, 1); - apply_pio_workaround(BCM43xx_MMIO_PIO3_BASE, 2); - apply_pio_workaround(BCM43xx_MMIO_PIO4_BASE, 3); - -#undef apply_pio_workaround + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3); } - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, - reason & mask); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, bcm->dma_reason[0]); @@ -1860,7 +1846,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re { irqreturn_t ret = IRQ_HANDLED; struct bcm43xx_private *bcm = dev_id; - u32 reason, mask; + u32 reason; if (!bcm) return IRQ_NONE; @@ -1873,11 +1859,20 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re ret = IRQ_NONE; goto out; } - mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!(reason & mask)) + reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + if (!reason) goto out; - bcm43xx_interrupt_ack(bcm, reason, mask); + bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) + & 0x0001dc00; + bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) + & 0x0000dc00; + bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) + & 0x0000dc00; + bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) + & 0x0001dc00; + + bcm43xx_interrupt_ack(bcm, reason); /* Only accept IRQs, if we are initialized properly. * This avoids an RX race while initializing. |