b43: Remove unnecessary MMIO in interrupt hotpath

This removes unnecessary MMIO accesses in the interrupt hotpath.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Michael Buesch 2009-04-08 21:26:27 +02:00 committed by John W. Linville
parent a2caba6b5f
commit 1379072877
2 changed files with 21 additions and 44 deletions

View file

@ -778,8 +778,8 @@ struct b43_wldev {
/* Reason code of the last interrupt. */ /* Reason code of the last interrupt. */
u32 irq_reason; u32 irq_reason;
u32 dma_reason[6]; u32 dma_reason[6];
/* saved irq enable/disable state bitfield. */ /* The currently active generic-interrupt mask. */
u32 irq_savedstate; u32 irq_mask;
/* Link Quality calculation context. */ /* Link Quality calculation context. */
struct b43_noise_calculation noisecalc; struct b43_noise_calculation noisecalc;
/* if > 0 MAC is suspended. if == 0 MAC is enabled. */ /* if > 0 MAC is suspended. if == 0 MAC is enabled. */

View file

@ -673,32 +673,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev)
b43_set_slot_time(dev, 20); b43_set_slot_time(dev, 20);
} }
/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
* Returns the _previously_ enabled IRQ mask.
*/
static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask)
{
u32 old_mask;
old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask);
return old_mask;
}
/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
* Returns the _previously_ enabled IRQ mask.
*/
static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask)
{
u32 old_mask;
old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
return old_mask;
}
/* Synchronize IRQ top- and bottom-half. /* Synchronize IRQ top- and bottom-half.
* IRQs must be masked before calling this. * IRQs must be masked before calling this.
* This must not be called with the irq_lock held. * This must not be called with the irq_lock held.
@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
/* This is the bottom half of the asynchronous beacon update. */ /* This is the bottom half of the asynchronous beacon update. */
/* Ignore interrupt in the future. */ /* Ignore interrupt in the future. */
dev->irq_savedstate &= ~B43_IRQ_BEACON; dev->irq_mask &= ~B43_IRQ_BEACON;
cmd = b43_read32(dev, B43_MMIO_MACCMD); cmd = b43_read32(dev, B43_MMIO_MACCMD);
beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
/* Schedule interrupt manually, if busy. */ /* Schedule interrupt manually, if busy. */
if (beacon0_valid && beacon1_valid) { if (beacon0_valid && beacon1_valid) {
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON); b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
dev->irq_savedstate |= B43_IRQ_BEACON; dev->irq_mask |= B43_IRQ_BEACON;
return; return;
} }
@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
spin_lock_irq(&wl->irq_lock); spin_lock_irq(&wl->irq_lock);
/* update beacon right away or defer to irq */ /* update beacon right away or defer to irq */
dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
handle_irq_beacon(dev); handle_irq_beacon(dev);
/* The handler might have updated the IRQ mask. */ /* The handler might have updated the IRQ mask. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
dev->irq_savedstate);
mmiowb(); mmiowb();
spin_unlock_irq(&wl->irq_lock); spin_unlock_irq(&wl->irq_lock);
} }
@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
if (reason & B43_IRQ_TX_OK) if (reason & B43_IRQ_TX_OK)
handle_irq_transmit_status(dev); handle_irq_transmit_status(dev);
b43_interrupt_enable(dev, dev->irq_savedstate); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
mmiowb(); mmiowb();
spin_unlock_irqrestore(&dev->wl->irq_lock, flags); spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
} }
@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason)
b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
/* Unused ring
b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]); b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
*/
} }
/* Interrupt handler top-half */ /* Interrupt handler top-half */
@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
struct b43_wldev *dev = dev_id; struct b43_wldev *dev = dev_id;
u32 reason; u32 reason;
if (!dev) B43_WARN_ON(!dev);
return IRQ_NONE;
spin_lock(&dev->wl->irq_lock); spin_lock(&dev->wl->irq_lock);
if (b43_status(dev) < B43_STAT_STARTED) if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
/* This can only happen on shared IRQ lines. */
goto out; goto out;
}
reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) /* shared IRQ */ if (reason == 0xffffffff) /* shared IRQ */
goto out; goto out;
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); reason &= dev->irq_mask;
if (!reason) if (!reason)
goto out; goto out;
@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
& 0x0001DC00; & 0x0001DC00;
dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON) dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
& 0x0000DC00; & 0x0000DC00;
/* Unused ring
dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON) dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
& 0x0000DC00; & 0x0000DC00;
*/
b43_interrupt_ack(dev, reason); b43_interrupt_ack(dev, reason);
/* disable all IRQs. They are enabled again in the bottom half. */ /* disable all IRQs. They are enabled again in the bottom half. */
dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
/* save the reason code and call our bottom half. */ /* save the reason code and call our bottom half. */
dev->irq_reason = reason; dev->irq_reason = reason;
tasklet_schedule(&dev->isr_tasklet); tasklet_schedule(&dev->isr_tasklet);
out: out:
mmiowb(); mmiowb();
spin_unlock(&dev->wl->irq_lock); spin_unlock(&dev->wl->irq_lock);
@ -3799,7 +3776,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
* setting the status to INITIALIZED, as the interrupt handler * setting the status to INITIALIZED, as the interrupt handler
* won't care about IRQs then. */ * won't care about IRQs then. */
spin_lock_irqsave(&wl->irq_lock, flags); spin_lock_irqsave(&wl->irq_lock, flags);
dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
b43_synchronize_irq(dev); b43_synchronize_irq(dev);
@ -3840,7 +3817,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
/* Start data flow (TX/RX). */ /* Start data flow (TX/RX). */
b43_mac_enable(dev); b43_mac_enable(dev);
b43_interrupt_enable(dev, dev->irq_savedstate); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
/* Start maintainance work */ /* Start maintainance work */
b43_periodic_tasks_setup(dev); b43_periodic_tasks_setup(dev);
@ -4003,9 +3980,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
/* IRQ related flags */ /* IRQ related flags */
dev->irq_reason = 0; dev->irq_reason = 0;
memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
dev->irq_savedstate = B43_IRQ_MASKTEMPLATE; dev->irq_mask = B43_IRQ_MASKTEMPLATE;
if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR; dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
dev->mac_suspended = 1; dev->mac_suspended = 1;