Commit f0734ab6 authored by Ayaz Abdulla's avatar Ayaz Abdulla Committed by Jeff Garzik

forcedeth: irq data path optimization

This patch optimizes the irq data paths and cleans up the code.
Signed-Off-By: default avatarAyaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent b01867cb
...@@ -2777,7 +2777,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -2777,7 +2777,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
} }
pci_push(base);
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
...@@ -2786,22 +2785,46 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -2786,22 +2785,46 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
nv_tx_done(dev); nv_tx_done(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
if (events & NVREG_IRQ_LINK) { #ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev);
/* Disable furthur receive irq's */
spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
else
writel(np->irqmask, base + NvRegIrqMask);
spin_unlock(&np->lock);
}
#else
if (nv_rx_process(dev, dev->weight)) {
if (unlikely(nv_alloc_rx(dev))) {
spin_lock(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock(&np->lock);
}
}
#endif
if (unlikely(events & NVREG_IRQ_LINK)) {
spin_lock(&np->lock); spin_lock(&np->lock);
nv_link_irq(dev); nv_link_irq(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
} }
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) {
spin_lock(&np->lock); spin_lock(&np->lock);
nv_linkchange(dev); nv_linkchange(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
np->link_timeout = jiffies + LINK_TIMEOUT; np->link_timeout = jiffies + LINK_TIMEOUT;
} }
if (events & (NVREG_IRQ_TX_ERR)) { if (unlikely(events & (NVREG_IRQ_TX_ERR))) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events); dev->name, events);
} }
if (events & (NVREG_IRQ_UNKNOWN)) { if (unlikely(events & (NVREG_IRQ_UNKNOWN))) {
printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
dev->name, events); dev->name, events);
} }
...@@ -2822,30 +2845,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -2822,30 +2845,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
spin_unlock(&np->lock); spin_unlock(&np->lock);
break; break;
} }
#ifdef CONFIG_FORCEDETH_NAPI if (unlikely(i > max_interrupt_work)) {
if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev);
/* Disable furthur receive irq's */
spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
else
writel(np->irqmask, base + NvRegIrqMask);
spin_unlock(&np->lock);
}
#else
nv_rx_process(dev, dev->weight);
if (nv_alloc_rx(dev)) {
spin_lock(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock(&np->lock);
}
#endif
if (i > max_interrupt_work) {
spin_lock(&np->lock); spin_lock(&np->lock);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
if (!(np->msi_flags & NV_MSI_X_ENABLED)) if (!(np->msi_flags & NV_MSI_X_ENABLED))
...@@ -2869,6 +2869,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -2869,6 +2869,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
return IRQ_RETVAL(i); return IRQ_RETVAL(i);
} }
#define TX_WORK_PER_LOOP 64
#define RX_WORK_PER_LOOP 64
/**
* All _optimized functions are used to help increase performance
* (reduce CPU and increase throughput). They use descripter version 3,
* compiler directives, and reduce memory accesses.
*/
static irqreturn_t nv_nic_irq_optimized(int foo, void *data) static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
{ {
struct net_device *dev = (struct net_device *) data; struct net_device *dev = (struct net_device *) data;
...@@ -2887,7 +2894,6 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) ...@@ -2887,7 +2894,6 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
} }
pci_push(base);
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
...@@ -2896,22 +2902,46 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) ...@@ -2896,22 +2902,46 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
nv_tx_done_optimized(dev); nv_tx_done_optimized(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
if (events & NVREG_IRQ_LINK) { #ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev);
/* Disable furthur receive irq's */
spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
else
writel(np->irqmask, base + NvRegIrqMask);
spin_unlock(&np->lock);
}
#else
if (nv_rx_process_optimized(dev, dev->weight)) {
if (unlikely(nv_alloc_rx_optimized(dev))) {
spin_lock(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock(&np->lock);
}
}
#endif
if (unlikely(events & NVREG_IRQ_LINK)) {
spin_lock(&np->lock); spin_lock(&np->lock);
nv_link_irq(dev); nv_link_irq(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
} }
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) {
spin_lock(&np->lock); spin_lock(&np->lock);
nv_linkchange(dev); nv_linkchange(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
np->link_timeout = jiffies + LINK_TIMEOUT; np->link_timeout = jiffies + LINK_TIMEOUT;
} }
if (events & (NVREG_IRQ_TX_ERR)) { if (unlikely(events & (NVREG_IRQ_TX_ERR))) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events); dev->name, events);
} }
if (events & (NVREG_IRQ_UNKNOWN)) { if (unlikely(events & (NVREG_IRQ_UNKNOWN))) {
printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
dev->name, events); dev->name, events);
} }
...@@ -2933,30 +2963,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) ...@@ -2933,30 +2963,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
break; break;
} }
#ifdef CONFIG_FORCEDETH_NAPI if (unlikely(i > max_interrupt_work)) {
if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev);
/* Disable furthur receive irq's */
spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
else
writel(np->irqmask, base + NvRegIrqMask);
spin_unlock(&np->lock);
}
#else
nv_rx_process_optimized(dev, dev->weight);
if (nv_alloc_rx_optimized(dev)) {
spin_lock(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock(&np->lock);
}
#endif
if (i > max_interrupt_work) {
spin_lock(&np->lock); spin_lock(&np->lock);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
if (!(np->msi_flags & NV_MSI_X_ENABLED)) if (!(np->msi_flags & NV_MSI_X_ENABLED))
...@@ -2994,7 +3001,6 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) ...@@ -2994,7 +3001,6 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
for (i=0; ; i++) { for (i=0; ; i++) {
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus); writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
pci_push(base);
dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events); dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events);
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
...@@ -3003,11 +3009,11 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) ...@@ -3003,11 +3009,11 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
nv_tx_done_optimized(dev); nv_tx_done_optimized(dev);
spin_unlock_irqrestore(&np->lock, flags); spin_unlock_irqrestore(&np->lock, flags);
if (events & (NVREG_IRQ_TX_ERR)) { if (unlikely(events & (NVREG_IRQ_TX_ERR))) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events); dev->name, events);
} }
if (i > max_interrupt_work) { if (unlikely(i > max_interrupt_work)) {
spin_lock_irqsave(&np->lock, flags); spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
...@@ -3105,20 +3111,20 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) ...@@ -3105,20 +3111,20 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
for (i=0; ; i++) { for (i=0; ; i++) {
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
pci_push(base);
dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events); dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
nv_rx_process_optimized(dev, dev->weight); if (nv_rx_process_optimized(dev, dev->weight)) {
if (nv_alloc_rx_optimized(dev)) { if (unlikely(nv_alloc_rx_optimized(dev))) {
spin_lock_irqsave(&np->lock, flags); spin_lock_irqsave(&np->lock, flags);
if (!np->in_shutdown) if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL); mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock_irqrestore(&np->lock, flags); spin_unlock_irqrestore(&np->lock, flags);
} }
}
if (i > max_interrupt_work) { if (unlikely(i > max_interrupt_work)) {
spin_lock_irqsave(&np->lock, flags); spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
...@@ -3153,7 +3159,6 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) ...@@ -3153,7 +3159,6 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data)
for (i=0; ; i++) { for (i=0; ; i++) {
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER;
writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus); writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus);
pci_push(base);
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
...@@ -3187,7 +3192,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) ...@@ -3187,7 +3192,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data)
printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
dev->name, events); dev->name, events);
} }
if (i > max_interrupt_work) { if (unlikely(i > max_interrupt_work)) {
spin_lock_irqsave(&np->lock, flags); spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
...@@ -4969,7 +4974,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -4969,7 +4974,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = nv_poll_controller; dev->poll_controller = nv_poll_controller;
#endif #endif
dev->weight = 64; dev->weight = RX_WORK_PER_LOOP;
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
dev->poll = nv_napi_poll; dev->poll = nv_napi_poll;
#endif #endif
......
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