Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2662

kernel-2.6.18-238.el5.src.rpm

From: Ivan Vecera <ivecera@redhat.com>
Date: Wed, 8 Dec 2010 18:06:37 -0500
Subject: [net] forcedeth: fix race condition in latest backport
Message-id: <1291831597-24982-1-git-send-email-ivecera@redhat.com>
Patchwork-id: 30010
O-Subject: [RHEL5.6 PATCH] forcedeth: partially revert commit 1b2bb76
Bugzilla: 658434
RH-Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
RH-Acked-by: Andy Gospodarek <gospo@redhat.com>

BZs:
#658434 - forcedeth driver panics while booting debug kernel

Description:
This patch reverts part of the upstream commit introduced spin lock changes
that cause race condition found during testing. This is very strange issue
because it is reproducible only on sun-x4440-01.rhts.eng.bos.redhat.com and
only with i686 kernel-debug package.

Test status:
Tested by myself

Reverted upstream commit:
1b2bb76 forcedeth: fix irq clearing and napi spin lock changes

Signed-off-by: Ivan Vecera <ivecera@redhat.com>

diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index f256645..0c5dcf5 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -3447,6 +3447,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
 
 	nv_msi_workaround(np);
 
+	spin_lock(&np->lock);
 	if (netif_rx_schedule_prep(dev)) {
 		/*
 		 * Disable further irq's (msix not enabled with napi)
@@ -3454,6 +3455,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
 		writel(0, base + NvRegIrqMask);
 		__netif_rx_schedule(dev);
 	}
+	spin_unlock(&np->lock);
 
 	dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name);
 
@@ -3486,6 +3488,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data, struct pt_regs *reg
 
 	nv_msi_workaround(np);
 
+	spin_lock(&np->lock);
 	if (netif_rx_schedule_prep(dev)) {
 		/*
 		 * Disable further irq's (msix not enabled with napi)
@@ -3493,6 +3496,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data, struct pt_regs *reg
 		writel(0, base + NvRegIrqMask);
 		__netif_rx_schedule(dev);
 	}
+	spin_unlock(&np->lock);
 	dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name);
 
 	return IRQ_HANDLED;
@@ -3605,9 +3609,15 @@ static int nv_napi_poll(struct napi_struct *napi, int budget)
 	if (rx_work < budget) {
 		/* re-enable interrupts
 		   (msix not enabled in napi) */
-		napi_complete(napi);
+		napi_gro_flush(napi);
+
+		spin_lock_irqsave(&np->lock, flags);
+
+		__netif_rx_complete(dev);
 
 		writel(np->irqmask, base + NvRegIrqMask);
+
+		spin_unlock_irqrestore(&np->lock, flags);
 	}
 	return rx_work;
 }