[TG3]: Remove status block access in tg3_msi() and add prefetches

Remove unnecessary status block accesses in tg3_msi(). Since MSI is
not shared, it is unnecessary to read the status block to determine if
there are any new events in the MSI handler. It is also unnecessary to
clear the updated bit in the status block.

Since the poll list is per-cpu, tg3_poll() will be scheduled to run on
the same CPU that received the MSI. Prefetches for the status block
and the next rx descriptors are added in tg3_msi() to improve their
access times when tg3_poll() runs.

In the non-MSI irq handlers, we need to check the status block because
interrupts may be shared. Only prefetches for the next rx descriptors
are added.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Michael Chan 2005-09-05 17:53:19 -07:00 committed by David S. Miller
parent 9f40dead25
commit 61487480dd

View File

@ -36,6 +36,7 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/prefetch.h>
#include <net/checksum.h> #include <net/checksum.h>
@ -3278,8 +3279,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev); struct tg3 *tp = netdev_priv(dev);
struct tg3_hw_status *sblk = tp->hw_status;
prefetch(tp->hw_status);
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
/* /*
* Writing any value to intr-mbox-0 clears PCI INTA# and * Writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events. * chip-internal interrupt pending events.
@ -3288,19 +3290,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
* event coalescing. * event coalescing.
*/ */
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
tp->last_tag = sblk->status_tag; if (likely(!tg3_irq_sync(tp)))
rmb();
if (tg3_irq_sync(tp))
goto out;
sblk->status &= ~SD_STATUS_UPDATED;
if (likely(tg3_has_work(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */ netif_rx_schedule(dev); /* schedule NAPI poll */
else {
/* No work, re-enable interrupts. */
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
tp->last_tag << 24);
}
out:
return IRQ_RETVAL(1); return IRQ_RETVAL(1);
} }
@ -3330,9 +3322,10 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (tg3_irq_sync(tp)) if (tg3_irq_sync(tp))
goto out; goto out;
sblk->status &= ~SD_STATUS_UPDATED; sblk->status &= ~SD_STATUS_UPDATED;
if (likely(tg3_has_work(tp))) if (likely(tg3_has_work(tp))) {
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
netif_rx_schedule(dev); /* schedule NAPI poll */ netif_rx_schedule(dev); /* schedule NAPI poll */
else { } else {
/* No work, shared interrupt perhaps? re-enable /* No work, shared interrupt perhaps? re-enable
* interrupts, and flush that PCI write * interrupts, and flush that PCI write
*/ */
@ -3374,9 +3367,10 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
if (tg3_irq_sync(tp)) if (tg3_irq_sync(tp))
goto out; goto out;
sblk->status &= ~SD_STATUS_UPDATED; sblk->status &= ~SD_STATUS_UPDATED;
if (likely(tg3_has_work(tp))) if (likely(tg3_has_work(tp))) {
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
netif_rx_schedule(dev); /* schedule NAPI poll */ netif_rx_schedule(dev); /* schedule NAPI poll */
else { } else {
/* no work, shared interrupt perhaps? re-enable /* no work, shared interrupt perhaps? re-enable
* interrupts, and flush that PCI write * interrupts, and flush that PCI write
*/ */