summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormb <mb@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-04-08 19:03:10 +0000
committermb <mb@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-04-08 19:03:10 +0000
commit5bc450051be79bfae37ad1f185c4d2fb315d7fd7 (patch)
treeeec8ab48c5d0cd6c1278963bf111c3ad48dfd988
parent47a4d53758f5f6fd94b192ba9373e16040b1ea17 (diff)
b43: Remove unnecessary MMIO accesses in the interrupt hotpath.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@15160 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--package/mac80211/patches/530-b43-optimize-hotpath-mmio.patch177
1 files changed, 177 insertions, 0 deletions
diff --git a/package/mac80211/patches/530-b43-optimize-hotpath-mmio.patch b/package/mac80211/patches/530-b43-optimize-hotpath-mmio.patch
new file mode 100644
index 000000000..341373199
--- /dev/null
+++ b/package/mac80211/patches/530-b43-optimize-hotpath-mmio.patch
@@ -0,0 +1,177 @@
+Index: compat-wireless-2009-03-31/drivers/net/wireless/b43/b43.h
+===================================================================
+--- compat-wireless-2009-03-31.orig/drivers/net/wireless/b43/b43.h 2009-04-08 20:27:37.000000000 +0200
++++ compat-wireless-2009-03-31/drivers/net/wireless/b43/b43.h 2009-04-08 20:28:14.000000000 +0200
+@@ -778,8 +778,8 @@ struct b43_wldev {
+ /* Reason code of the last interrupt. */
+ u32 irq_reason;
+ u32 dma_reason[6];
+- /* saved irq enable/disable state bitfield. */
+- u32 irq_savedstate;
++ /* The currently active generic-interrupt mask. */
++ u32 irq_mask;
+ /* Link Quality calculation context. */
+ struct b43_noise_calculation noisecalc;
+ /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+Index: compat-wireless-2009-03-31/drivers/net/wireless/b43/main.c
+===================================================================
+--- compat-wireless-2009-03-31.orig/drivers/net/wireless/b43/main.c 2009-04-08 20:22:24.000000000 +0200
++++ compat-wireless-2009-03-31/drivers/net/wireless/b43/main.c 2009-04-08 20:41:43.000000000 +0200
+@@ -673,32 +673,6 @@ static void b43_short_slot_timing_disabl
+ 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.
+ * IRQs must be masked before calling this.
+ * This must not be called with the irq_lock held.
+@@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43
+ /* This is the bottom half of the asynchronous beacon update. */
+
+ /* Ignore interrupt in the future. */
+- dev->irq_savedstate &= ~B43_IRQ_BEACON;
++ dev->irq_mask &= ~B43_IRQ_BEACON;
+
+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
+ beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
+@@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43
+ /* Schedule interrupt manually, if busy. */
+ if (beacon0_valid && beacon1_valid) {
+ b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
+- dev->irq_savedstate |= B43_IRQ_BEACON;
++ dev->irq_mask |= B43_IRQ_BEACON;
+ return;
+ }
+
+@@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_wo
+ if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
+ spin_lock_irq(&wl->irq_lock);
+ /* update beacon right away or defer to irq */
+- dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
+ handle_irq_beacon(dev);
+ /* The handler might have updated the IRQ mask. */
+- b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
+- dev->irq_savedstate);
++ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+ mmiowb();
+ spin_unlock_irq(&wl->irq_lock);
+ }
+@@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct
+ if (reason & B43_IRQ_TX_OK)
+ handle_irq_transmit_status(dev);
+
+- b43_interrupt_enable(dev, dev->irq_savedstate);
++ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+ mmiowb();
+ spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
+ }
+@@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43
+ 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_DMA4_REASON, dev->dma_reason[4]);
++/* Unused ring
+ b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
++*/
+ }
+
+ /* Interrupt handler top-half */
+@@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler
+ struct b43_wldev *dev = dev_id;
+ u32 reason;
+
+- if (!dev)
+- return IRQ_NONE;
++ B43_WARN_ON(!dev);
+
+ 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;
++ }
+ reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+ if (reason == 0xffffffff) /* shared IRQ */
+ goto out;
+ ret = IRQ_HANDLED;
+- reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
++ reason &= dev->irq_mask;
+ if (!reason)
+ goto out;
+
+@@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler
+ & 0x0001DC00;
+ dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
+ & 0x0000DC00;
++/* Unused ring
+ dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
+ & 0x0000DC00;
++*/
+
+ b43_interrupt_ack(dev, reason);
+ /* 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. */
+ dev->irq_reason = reason;
+ tasklet_schedule(&dev->isr_tasklet);
+- out:
++out:
+ mmiowb();
+ spin_unlock(&dev->wl->irq_lock);
+
+@@ -3799,7 +3776,7 @@ static void b43_wireless_core_stop(struc
+ * setting the status to INITIALIZED, as the interrupt handler
+ * won't care about IRQs then. */
+ 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 */
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43_synchronize_irq(dev);
+@@ -3840,7 +3817,7 @@ static int b43_wireless_core_start(struc
+
+ /* Start data flow (TX/RX). */
+ 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 */
+ b43_periodic_tasks_setup(dev);
+@@ -3998,9 +3975,9 @@ static void setup_struct_wldev_for_init(
+ /* IRQ related flags */
+ dev->irq_reason = 0;
+ 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)
+- dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR;
++ dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
+
+ dev->mac_suspended = 1;
+