[patch 37/47] forcedeth: msi interrupts

From: Greg KH
Date: Fri Jun 13 2008 - 20:24:45 EST


-stable review patch. If anyone has any objections, please let us know.

------------------
From: Ayaz Abdulla <aabdulla@xxxxxxxxxx>

commit 4db0ee176e256444695ee2d7b004552e82fec987 upstream

Add a workaround for lost MSI interrupts. There is a race condition in
the HW in which future interrupts could be missed. The workaround is to
toggle the MSI irq mask.

Added cleanup based on comments from Andrew Morton.

Signed-off-by: Ayaz Abdulla <aabdulla@xxxxxxxxxx>
Cc: Manfred Spraul <manfred@xxxxxxxxxxxxxxxx>
Cc: Jeff Garzik <jeff@xxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Jeff Garzik <jgarzik@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
drivers/net/forcedeth.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -3111,6 +3111,20 @@ static void nv_link_irq(struct net_devic
dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name);
}

+static void nv_msi_workaround(struct fe_priv *np)
+{
+
+ /* 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) {
+ u8 __iomem *base = np->base;
+
+ 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;
@@ -3133,6 +3147,8 @@ static irqreturn_t nv_nic_irq(int foo, v
if (!(events & np->irqmask))
break;

+ nv_msi_workaround(np);
+
spin_lock(&np->lock);
nv_tx_done(dev);
spin_unlock(&np->lock);
@@ -3248,6 +3264,8 @@ static irqreturn_t nv_nic_irq_optimized(
if (!(events & np->irqmask))
break;

+ nv_msi_workaround(np);
+
spin_lock(&np->lock);
nv_tx_done_optimized(dev, TX_WORK_PER_LOOP);
spin_unlock(&np->lock);
@@ -3588,6 +3606,8 @@ static irqreturn_t nv_nic_irq_test(int f
if (!(events & NVREG_IRQ_TIMER))
return IRQ_RETVAL(0);

+ nv_msi_workaround(np);
+
spin_lock(&np->lock);
np->intr_test = 1;
spin_unlock(&np->lock);

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/