+static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct fe_priv *np = netdev_priv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ u32 events;
+ int i;
+
+ dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);
+
+ for (i=0; ; i++) {
+ events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
+ writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
+ pci_push(base);
+ dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events);
+ if (!(events & np->irqmask))
+ break;
+
+ spin_lock(&np->lock);
+ nv_tx_done(dev);
+ spin_unlock(&np->lock);
+
+ if (events & (NVREG_IRQ_TX_ERR)) {
+ dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
+ dev->name, events);
+ }
+ if (i > max_interrupt_work) {
+ spin_lock(&np->lock);
+ /* disable interrupts on the nic */
+ writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
+ pci_push(base);
+
+ if (!np->in_shutdown) {
+ np->nic_poll_irq |= NVREG_IRQ_TX_ALL;
+ mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+ }
+ printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
+ spin_unlock(&np->lock);
+ break;
+ }
+
+ }
+ dprintk(KERN_DEBUG "%s: nv_nic_irq_tx completed\n", dev->name);
+
+ return IRQ_RETVAL(i);
+}
+
+static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct fe_priv *np = netdev_priv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ u32 events;
+ int i;
+
+ dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name);
+
+ for (i=0; ; i++) {
+ events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
+ writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
+ pci_push(base);
+ dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
+ if (!(events & np->irqmask))
+ break;
+
+ nv_rx_process(dev);
+ 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);
+ }
+
+ if (i > max_interrupt_work) {
+ spin_lock(&np->lock);
+ /* disable interrupts on the nic */
+ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+ pci_push(base);
+
+ if (!np->in_shutdown) {
+ np->nic_poll_irq |= NVREG_IRQ_RX_ALL;
+ mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+ }
+ printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
+ spin_unlock(&np->lock);
+ break;
+ }
+
+ }
+ dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name);
+
+ return IRQ_RETVAL(i);
+}
+
+static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct fe_priv *np = netdev_priv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ u32 events;
+ int i;
+
+ dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name);
+
+ for (i=0; ; i++) {
+ events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER;
+ writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus);
+ pci_push(base);
+ dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
+ if (!(events & np->irqmask))
+ break;
+
+ if (events & NVREG_IRQ_LINK) {
+ spin_lock(&np->lock);
+ nv_link_irq(dev);
+ spin_unlock(&np->lock);
+ }
+ if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
+ spin_lock(&np->lock);
+ nv_linkchange(dev);
+ spin_unlock(&np->lock);
+ np->link_timeout = jiffies + LINK_TIMEOUT;
+ }
+ if (events & (NVREG_IRQ_UNKNOWN)) {
+ printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
+ dev->name, events);
+ }
+ if (i > max_interrupt_work) {
+ spin_lock(&np->lock);
+ /* disable interrupts on the nic */
+ writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
+ pci_push(base);
+
+ if (!np->in_shutdown) {
+ np->nic_poll_irq |= NVREG_IRQ_OTHER;
+ mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+ }
+ printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
+ spin_unlock(&np->lock);
+ break;
+ }
+
+ }
+ dprintk(KERN_DEBUG "%s: nv_nic_irq_other completed\n", dev->name);
+
+ return IRQ_RETVAL(i);
+}
+