Commit 44710bbc authored by Stefano Brivio's avatar Stefano Brivio Committed by John W. Linville

b43legacy: Remove unnecessary MMIO in interrupt hotpath

This removes unnecessary MMIO accesses in the interrupt hotpath. The
patch by Michael Buesch for b43 has been ported to b43legacy.
Signed-off-by: default avatarStefano Brivio <stefano.brivio@polimi.it>
Tested-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6b96f93e
...@@ -694,8 +694,8 @@ struct b43legacy_wldev { ...@@ -694,8 +694,8 @@ struct b43legacy_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 b43legacy_noise_calculation noisecalc; struct b43legacy_noise_calculation noisecalc;
/* if > 0 MAC is suspended. if == 0 MAC is enabled. */ /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
......
...@@ -583,35 +583,6 @@ static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev) ...@@ -583,35 +583,6 @@ static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
b43legacy_set_slot_time(dev, 20); 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. /* 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.
...@@ -1200,7 +1171,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) ...@@ -1200,7 +1171,7 @@ static void handle_irq_beacon(struct b43legacy_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 &= ~B43legacy_IRQ_BEACON; dev->irq_mask &= ~B43legacy_IRQ_BEACON;
cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
...@@ -1209,7 +1180,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) ...@@ -1209,7 +1180,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
/* Schedule interrupt manually, if busy. */ /* Schedule interrupt manually, if busy. */
if (beacon0_valid && beacon1_valid) { if (beacon0_valid && beacon1_valid) {
b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
dev->irq_savedstate |= B43legacy_IRQ_BEACON; dev->irq_mask |= B43legacy_IRQ_BEACON;
return; return;
} }
...@@ -1247,12 +1218,11 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work) ...@@ -1247,12 +1218,11 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
dev = wl->current_dev; dev = wl->current_dev;
if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) { if (likely(dev && (b43legacy_status(dev) >= B43legacy_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 = b43legacy_read32(dev, B43legacy_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. */
b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
dev->irq_savedstate); dev->irq_mask);
mmiowb(); mmiowb();
spin_unlock_irq(&wl->irq_lock); spin_unlock_irq(&wl->irq_lock);
} }
...@@ -1398,7 +1368,7 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) ...@@ -1398,7 +1368,7 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
if (reason & B43legacy_IRQ_TX_OK) if (reason & B43legacy_IRQ_TX_OK)
handle_irq_transmit_status(dev); handle_irq_transmit_status(dev);
b43legacy_interrupt_enable(dev, dev->irq_savedstate); b43legacy_write32(dev, B43legacy_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);
} }
...@@ -1450,18 +1420,18 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id) ...@@ -1450,18 +1420,18 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
struct b43legacy_wldev *dev = dev_id; struct b43legacy_wldev *dev = dev_id;
u32 reason; u32 reason;
if (!dev) B43legacy_WARN_ON(!dev);
return IRQ_NONE;
spin_lock(&dev->wl->irq_lock); 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; goto out;
reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); reason = b43legacy_read32(dev, B43legacy_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 &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); reason &= dev->irq_mask;
if (!reason) if (!reason)
goto out; goto out;
...@@ -1485,10 +1455,9 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id) ...@@ -1485,10 +1455,9 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
& 0x0000DC00; & 0x0000DC00;
b43legacy_interrupt_ack(dev, reason); b43legacy_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 = b43legacy_interrupt_disable(dev, b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
B43legacy_IRQ_ALL); /* 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:
...@@ -1948,7 +1917,8 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev) ...@@ -1948,7 +1917,8 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
/* Re-enable IRQs. */ /* Re-enable IRQs. */
spin_lock_irq(&dev->wl->irq_lock); 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); spin_unlock_irq(&dev->wl->irq_lock);
} }
} }
...@@ -1967,10 +1937,9 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev) ...@@ -1967,10 +1937,9 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
/* Mask IRQs before suspending MAC. Otherwise /* Mask IRQs before suspending MAC. Otherwise
* the MAC stays busy and won't suspend. */ * the MAC stays busy and won't suspend. */
spin_lock_irq(&dev->wl->irq_lock); 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); spin_unlock_irq(&dev->wl->irq_lock);
b43legacy_synchronize_irq(dev); b43legacy_synchronize_irq(dev);
dev->irq_savedstate = tmp;
b43legacy_power_saving_ctl_bits(dev, -1, 1); b43legacy_power_saving_ctl_bits(dev, -1, 1);
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
...@@ -2659,7 +2628,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, ...@@ -2659,7 +2628,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
int antenna_tx; int antenna_tx;
int antenna_rx; int antenna_rx;
int err = 0; int err = 0;
u32 savedirqs;
antenna_tx = B43legacy_ANTENNA_DEFAULT; antenna_tx = B43legacy_ANTENNA_DEFAULT;
antenna_rx = B43legacy_ANTENNA_DEFAULT; antenna_rx = B43legacy_ANTENNA_DEFAULT;
...@@ -2699,7 +2667,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, ...@@ -2699,7 +2667,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
goto out_unlock_mutex; 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); spin_unlock_irqrestore(&wl->irq_lock, flags);
b43legacy_synchronize_irq(dev); b43legacy_synchronize_irq(dev);
...@@ -2738,7 +2706,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, ...@@ -2738,7 +2706,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
} }
spin_lock_irqsave(&wl->irq_lock, flags); spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_interrupt_enable(dev, savedirqs); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
mmiowb(); mmiowb();
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
out_unlock_mutex: out_unlock_mutex:
...@@ -2801,7 +2769,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2801,7 +2769,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
struct b43legacy_wldev *dev; struct b43legacy_wldev *dev;
struct b43legacy_phy *phy; struct b43legacy_phy *phy;
unsigned long flags; unsigned long flags;
u32 savedirqs;
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
B43legacy_WARN_ON(wl->vif != vif); B43legacy_WARN_ON(wl->vif != vif);
...@@ -2817,7 +2784,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2817,7 +2784,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
goto out_unlock_mutex; 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) { if (changed & BSS_CHANGED_BSSID) {
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
...@@ -2862,7 +2829,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2862,7 +2829,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
b43legacy_mac_enable(dev); b43legacy_mac_enable(dev);
spin_lock_irqsave(&wl->irq_lock, flags); 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? */ /* XXX: why? */
mmiowb(); mmiowb();
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
...@@ -2922,8 +2889,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) ...@@ -2922,8 +2889,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_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 = b43legacy_interrupt_disable(dev, b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
B43legacy_IRQ_ALL);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
b43legacy_synchronize_irq(dev); b43legacy_synchronize_irq(dev);
...@@ -2963,7 +2929,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev) ...@@ -2963,7 +2929,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)
/* Start data flow (TX/RX) */ /* Start data flow (TX/RX) */
b43legacy_mac_enable(dev); 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 */ /* Start maintenance work */
b43legacy_periodic_tasks_setup(dev); b43legacy_periodic_tasks_setup(dev);
...@@ -3126,7 +3092,7 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) ...@@ -3126,7 +3092,7 @@ static void setup_struct_wldev_for_init(struct b43legacy_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 = B43legacy_IRQ_MASKTEMPLATE; dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE;
dev->mac_suspended = 1; dev->mac_suspended = 1;
......
...@@ -443,7 +443,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev) ...@@ -443,7 +443,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev)
pio->queue3 = queue; pio->queue3 = queue;
if (dev->dev->id.revision < 3) 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"); b43legacydbg(dev->wl, "PIO initialized\n");
err = 0; err = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment