Search Linux Wireless

[PATCH 1/2] b43legacy: Remove unnecessary MMIO in interrupt hotpath

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Stefano Brivio <stefano.brivio@xxxxxxxxx>

This removes unnecessary MMIO accesses in the interrupt hotpath. The
patch by Michael Buesch for b43 has been ported to b43legacy.

Signed-off-by: Michael Buesch <mb@xxxxxxxxx>
Signed-off-by: Stefano Brivio <stefano.brivio@xxxxxxxxx>
Tested-by: Larry Finger <Larry.Finger@xxxxxxxxxxxx>
---

John,

This is 2.6.31 material. I am submitting this for Stefano because
this patch touches a section of the code that had to be changed
to fix the locking problem addressed in Patch 2/2.

I hope this patch does not cause any problems. My normal method
is not available while I'm away from home.

Larry
---

Index: wireless-testing/drivers/net/wireless/b43legacy/b43legacy.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43legacy/b43legacy.h
+++ wireless-testing/drivers/net/wireless/b43legacy/b43legacy.h
@@ -694,8 +694,8 @@ struct b43legacy_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 b43legacy_noise_calculation noisecalc;
 	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
Index: wireless-testing/drivers/net/wireless/b43legacy/main.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43legacy/main.c
+++ wireless-testing/drivers/net/wireless/b43legacy/main.c
@@ -583,35 +583,6 @@ static void b43legacy_short_slot_timing_
 	b43legacy_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 b43legacy_interrupt_enable(struct b43legacy_wldev *dev,
-					     u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
-	b43legacy_write32(dev, B43legacy_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 b43legacy_interrupt_disable(struct b43legacy_wldev *dev,
-					      u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
-	b43legacy_write32(dev, B43legacy_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.
@@ -1200,7 +1171,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 &= ~B43legacy_IRQ_BEACON;
+	dev->irq_mask &= ~B43legacy_IRQ_BEACON;

 	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 	beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
@@ -1209,7 +1180,7 @@ static void handle_irq_beacon(struct b43
 	/* Schedule interrupt manually, if busy. */
 	if (beacon0_valid && beacon1_valid) {
 		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
-		dev->irq_savedstate |= B43legacy_IRQ_BEACON;
+		dev->irq_mask |= B43legacy_IRQ_BEACON;
 		return;
 	}

@@ -1247,12 +1218,11 @@ static void b43legacy_beacon_update_trig
 	dev = wl->current_dev;
 	if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) {
 		spin_lock_irq(&wl->irq_lock);
-		/* update beacon right away or defer to irq */
-		dev->irq_savedstate = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
+		/* Update beacon right away or defer to IRQ. */
 		handle_irq_beacon(dev);
 		/* The handler might have updated the IRQ mask. */
 		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
-			    dev->irq_savedstate);
+				  dev->irq_mask);
 		mmiowb();
 		spin_unlock_irq(&wl->irq_lock);
 	}
@@ -1398,7 +1368,7 @@ static void b43legacy_interrupt_tasklet(
 	if (reason & B43legacy_IRQ_TX_OK)
 		handle_irq_transmit_status(dev);

-	b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	mmiowb();
 	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
 }
@@ -1431,16 +1401,18 @@ static void b43legacy_interrupt_ack(stru

 	b43legacy_write32(dev, B43legacy_MMIO_DMA0_REASON,
 			  dev->dma_reason[0]);
-	b43legacy_write32(dev, B43legacy_MMIO_DMA1_REASON,
-			  dev->dma_reason[1]);
-	b43legacy_write32(dev, B43legacy_MMIO_DMA2_REASON,
-			  dev->dma_reason[2]);
-	b43legacy_write32(dev, B43legacy_MMIO_DMA3_REASON,
-			  dev->dma_reason[3]);
-	b43legacy_write32(dev, B43legacy_MMIO_DMA4_REASON,
-			  dev->dma_reason[4]);
-	b43legacy_write32(dev, B43legacy_MMIO_DMA5_REASON,
-			  dev->dma_reason[5]);
+/* Unused rings.
+ *	b43legacy_write32(dev, B43legacy_MMIO_DMA1_REASON,
+ *			  dev->dma_reason[1]);
+ *	b43legacy_write32(dev, B43legacy_MMIO_DMA2_REASON,
+ *			  dev->dma_reason[2]);
+ *	b43legacy_write32(dev, B43legacy_MMIO_DMA3_REASON,
+ *			  dev->dma_reason[3]);
+ *	b43legacy_write32(dev, B43legacy_MMIO_DMA4_REASON,
+ *			  dev->dma_reason[4]);
+ *	b43legacy_write32(dev, B43legacy_MMIO_DMA5_REASON,
+ *			  dev->dma_reason[5]);
+ */
 }

 /* Interrupt handler top-half */
@@ -1450,45 +1422,46 @@ static irqreturn_t b43legacy_interrupt_h
 	struct b43legacy_wldev *dev = dev_id;
 	u32 reason;

-	if (!dev)
-		return IRQ_NONE;
+	B43legacy_WARN_ON(!dev);

 	spin_lock(&dev->wl->irq_lock);

-	if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+	if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
+		/* This can only happen on shared IRQ lines. */
 		goto out;
 	reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff) /* shared IRQ */
 		goto out;
 	ret = IRQ_HANDLED;
-	reason &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
+	reason &= dev->irq_mask;
 	if (!reason)
 		goto out;

 	dev->dma_reason[0] = b43legacy_read32(dev,
 					      B43legacy_MMIO_DMA0_REASON)
 					      & 0x0001DC00;
-	dev->dma_reason[1] = b43legacy_read32(dev,
-					      B43legacy_MMIO_DMA1_REASON)
-					      & 0x0000DC00;
-	dev->dma_reason[2] = b43legacy_read32(dev,
-					      B43legacy_MMIO_DMA2_REASON)
-					      & 0x0000DC00;
-	dev->dma_reason[3] = b43legacy_read32(dev,
-					      B43legacy_MMIO_DMA3_REASON)
-					      & 0x0001DC00;
-	dev->dma_reason[4] = b43legacy_read32(dev,
-					      B43legacy_MMIO_DMA4_REASON)
-					      & 0x0000DC00;
-	dev->dma_reason[5] = b43legacy_read32(dev,
-					      B43legacy_MMIO_DMA5_REASON)
-					      & 0x0000DC00;
+/* Unused rings.
+ *	dev->dma_reason[1] = b43legacy_read32(dev,
+ *					      B43legacy_MMIO_DMA1_REASON)
+ *					      & 0x0000DC00;
+ *	dev->dma_reason[2] = b43legacy_read32(dev,
+ *					      B43legacy_MMIO_DMA2_REASON)
+ *					      & 0x0000DC00;
+ *	dev->dma_reason[3] = b43legacy_read32(dev,
+ *					      B43legacy_MMIO_DMA3_REASON)
+ *					      & 0x0001DC00;
+ *	dev->dma_reason[4] = b43legacy_read32(dev,
+ *					      B43legacy_MMIO_DMA4_REASON)
+ *					      & 0x0000DC00;
+ *	dev->dma_reason[5] = b43legacy_read32(dev,
+ *					      B43legacy_MMIO_DMA5_REASON)
+ *					      & 0x0000DC00;
+ */

 	b43legacy_interrupt_ack(dev, reason);
-	/* disable all IRQs. They are enabled again in the bottom half. */
-	dev->irq_savedstate = b43legacy_interrupt_disable(dev,
-							  B43legacy_IRQ_ALL);
-	/* save the reason code and call our bottom half. */
+	/* Disable all IRQs. They are enabled again in the bottom half. */
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+	/* Save the reason code and call our bottom half. */
 	dev->irq_reason = reason;
 	tasklet_schedule(&dev->isr_tasklet);
 out:
@@ -1948,7 +1921,8 @@ void b43legacy_mac_enable(struct b43lega

 		/* Re-enable IRQs. */
 		spin_lock_irq(&dev->wl->irq_lock);
-		b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+				  dev->irq_mask);
 		spin_unlock_irq(&dev->wl->irq_lock);
 	}
 }
@@ -1967,10 +1941,9 @@ void b43legacy_mac_suspend(struct b43leg
 		/* Mask IRQs before suspending MAC. Otherwise
 		 * the MAC stays busy and won't suspend. */
 		spin_lock_irq(&dev->wl->irq_lock);
-		tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
 		spin_unlock_irq(&dev->wl->irq_lock);
 		b43legacy_synchronize_irq(dev);
-		dev->irq_savedstate = tmp;

 		b43legacy_power_saving_ctl_bits(dev, -1, 1);
 		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
@@ -2659,7 +2632,6 @@ static int b43legacy_op_dev_config(struc
 	int antenna_tx;
 	int antenna_rx;
 	int err = 0;
-	u32 savedirqs;

 	antenna_tx = B43legacy_ANTENNA_DEFAULT;
 	antenna_rx = B43legacy_ANTENNA_DEFAULT;
@@ -2699,7 +2671,7 @@ static int b43legacy_op_dev_config(struc
 		spin_unlock_irqrestore(&wl->irq_lock, flags);
 		goto out_unlock_mutex;
 	}
-	savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 	b43legacy_synchronize_irq(dev);

@@ -2738,7 +2710,7 @@ static int b43legacy_op_dev_config(struc
 	}

 	spin_lock_irqsave(&wl->irq_lock, flags);
-	b43legacy_interrupt_enable(dev, savedirqs);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	mmiowb();
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 out_unlock_mutex:
@@ -2801,7 +2773,6 @@ static void b43legacy_op_bss_info_change
 	struct b43legacy_wldev *dev;
 	struct b43legacy_phy *phy;
 	unsigned long flags;
-	u32 savedirqs;

 	mutex_lock(&wl->mutex);
 	B43legacy_WARN_ON(wl->vif != vif);
@@ -2817,7 +2788,7 @@ static void b43legacy_op_bss_info_change
 		spin_unlock_irqrestore(&wl->irq_lock, flags);
 		goto out_unlock_mutex;
 	}
-	savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);

 	if (changed & BSS_CHANGED_BSSID) {
 		spin_unlock_irqrestore(&wl->irq_lock, flags);
@@ -2862,7 +2833,7 @@ static void b43legacy_op_bss_info_change
 	b43legacy_mac_enable(dev);

 	spin_lock_irqsave(&wl->irq_lock, flags);
-	b43legacy_interrupt_enable(dev, savedirqs);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	/* XXX: why? */
 	mmiowb();
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
@@ -2922,8 +2893,7 @@ static void b43legacy_wireless_core_stop
 	 * 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 = b43legacy_interrupt_disable(dev,
-							  B43legacy_IRQ_ALL);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
 	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 	b43legacy_synchronize_irq(dev);
@@ -2963,7 +2933,7 @@ static int b43legacy_wireless_core_start

 	/* Start data flow (TX/RX) */
 	b43legacy_mac_enable(dev);
-	b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);

 	/* Start maintenance work */
 	b43legacy_periodic_tasks_setup(dev);
@@ -3126,7 +3096,7 @@ 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 = B43legacy_IRQ_MASKTEMPLATE;
+	dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE;

 	dev->mac_suspended = 1;

Index: wireless-testing/drivers/net/wireless/b43legacy/pio.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43legacy/pio.c
+++ wireless-testing/drivers/net/wireless/b43legacy/pio.c
@@ -443,7 +443,7 @@ int b43legacy_pio_init(struct b43legacy_
 	pio->queue3 = queue;

 	if (dev->dev->id.revision < 3)
-		dev->irq_savedstate |= B43legacy_IRQ_PIO_WORKAROUND;
+		dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND;

 	b43legacydbg(dev->wl, "PIO initialized\n");
 	err = 0;




--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux