--- old/drivers/net/forcedeth.c 2008-06-03 16:16:26.000000000 -0400 +++ new/drivers/net/forcedeth.c 2008-06-03 16:31:44.000000000 -0400 @@ -3277,6 +3277,20 @@ dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); } +static inline void nv_msi_workaround(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + + /* Need to toggle the msi irq mask within the ethernet device, + * otherwise, future interrupts will not be detected. + */ + if (np->msi_flags & NV_MSI_ENABLED) { + writel(0, base + NvRegMSIIrqMask); + writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + } +} + static irqreturn_t nv_nic_irq(int foo, void *data) { struct net_device *dev = (struct net_device *) data; @@ -3299,6 +3313,8 @@ if (!(events & np->irqmask)) break; + nv_msi_workaround(dev); + spin_lock(&np->lock); nv_tx_done(dev); spin_unlock(&np->lock); @@ -3414,6 +3430,8 @@ if (!(events & np->irqmask)) break; + nv_msi_workaround(dev); + spin_lock(&np->lock); nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); spin_unlock(&np->lock); @@ -3754,6 +3772,8 @@ if (!(events & NVREG_IRQ_TIMER)) return IRQ_RETVAL(0); + nv_msi_workaround(dev); + spin_lock(&np->lock); np->intr_test = 1; spin_unlock(&np->lock);