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: Stefano Brivio <stefano.brivio@polimi.it> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
6b96f93e96
commit
44710bbc07
|
@ -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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
& 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)
|
||||||
|
|
||||||
/* 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)
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
* 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)
|
||||||
|
|
||||||
/* 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)
|
||||||
/* 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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue