[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:
Родитель
9f40dead25
Коммит
61487480dd
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче