Skip to content

Commit

Permalink
b43legacy: Remove unnecessary MMIO in interrupt hotpath
Browse files Browse the repository at this point in the history
This removes unnecessary MMIO accesses in the interrupt hotpath. The
patch by Michael Buesch for b43 has been ported to b43legacy.

Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it>
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Stefano Brivio authored and John W. Linville committed May 20, 2009
1 parent 6b96f93 commit 44710bb
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 59 deletions.
4 changes: 2 additions & 2 deletions drivers/net/wireless/b43legacy/b43legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
78 changes: 22 additions & 56 deletions drivers/net/wireless/b43legacy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,35 +583,6 @@ static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
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.
Expand Down Expand Up @@ -1200,7 +1171,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
/* 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);
Expand All @@ -1209,7 +1180,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
/* 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;
}

Expand Down Expand Up @@ -1247,12 +1218,11 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
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);
}
Expand Down Expand Up @@ -1398,7 +1368,7 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
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);
}
Expand Down Expand Up @@ -1450,18 +1420,18 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
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;

Expand All @@ -1485,10 +1455,9 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
& 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:
Expand Down Expand Up @@ -1948,7 +1917,8 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)

/* 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);
}
}
Expand All @@ -1967,10 +1937,9 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
/* 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,
Expand Down Expand Up @@ -2659,7 +2628,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
int antenna_tx;
int antenna_rx;
int err = 0;
u32 savedirqs;

antenna_tx = B43legacy_ANTENNA_DEFAULT;
antenna_rx = B43legacy_ANTENNA_DEFAULT;
Expand Down Expand Up @@ -2699,7 +2667,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
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);

Expand Down Expand Up @@ -2738,7 +2706,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
}

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:
Expand Down Expand Up @@ -2801,7 +2769,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
struct b43legacy_wldev *dev;
struct b43legacy_phy *phy;
unsigned long flags;
u32 savedirqs;

mutex_lock(&wl->mutex);
B43legacy_WARN_ON(wl->vif != vif);
Expand All @@ -2817,7 +2784,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
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);
Expand Down Expand Up @@ -2862,7 +2829,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
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);
Expand Down Expand Up @@ -2922,8 +2889,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
* 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);
Expand Down Expand Up @@ -2963,7 +2929,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)

/* 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);
Expand Down Expand Up @@ -3126,7 +3092,7 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
/* 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;

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/b43legacy/pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev)
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;
Expand Down

0 comments on commit 44710bb

Please sign in to comment.