[gPXE-devel] [PATCH] [sky2] Disable interrupts by default

Stefan Hajnoczi stefanha at gmail.com
Thu Jul 29 14:56:45 EDT 2010


Device interrupts should be disabled by default in the sky2 driver.
They are explicitly enabled when a PXE NBP client program uses the UNDI
interface, which is designed around interrupts.  Having interrupts
enabled when no handler is installed to service them results in hangs
because the spurious interrupt is never reset and remains high.

Signed-off-by: Stefan Hajnoczi <stefanha at gmail.com>
---
I wrote this on the train.  Now after comparing against Daniel's original patch
it is very similar and so may require further debugging to get the UNDI case
working.

 src/drivers/net/sky2.c |   24 ++++++++++--------------
 1 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/drivers/net/sky2.c b/src/drivers/net/sky2.c
index 00940af..07487ac 100644
--- a/src/drivers/net/sky2.c
+++ b/src/drivers/net/sky2.c
@@ -1130,7 +1130,7 @@ static int sky2_up(struct net_device *dev)
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
 	unsigned port = sky2->port;
-	u32 imask, ramsize;
+	u32 ramsize;
 	int err = -ENOMEM;
 
 	netdev_link_down(dev);
@@ -1198,11 +1198,6 @@ static int sky2_up(struct net_device *dev)
 	if (err)
 		goto err_out;
 
-	/* Enable interrupts from phy/mac for port */
-	imask = sky2_read32(hw, B0_IMSK);
-	imask |= portirq_msk[port];
-	sky2_write32(hw, B0_IMSK, imask);
-
 	DBGIO(PFX "%s: le bases: st %p [%x], rx %p [%x], tx %p [%x]\n",
 	      dev->name, hw->st_le, hw->st_dma, sky2->rx_le, sky2->rx_le_map,
 	      sky2->tx_le, sky2->tx_le_map);
@@ -1314,7 +1309,6 @@ static void sky2_down(struct net_device *dev)
 	struct sky2_hw *hw = sky2->hw;
 	unsigned port = sky2->port;
 	u16 ctrl;
-	u32 imask;
 
 	/* Never really got started! */
 	if (!sky2->tx_le)
@@ -1323,9 +1317,7 @@ static void sky2_down(struct net_device *dev)
 	DBG2(PFX "%s: disabling interface\n", dev->name);
 
 	/* Disable port IRQ */
-	imask = sky2_read32(hw, B0_IMSK);
-	imask &= ~portirq_msk[port];
-	sky2_write32(hw, B0_IMSK, imask);
+	netdev_irq(dev, 0);
 
 	sky2_gmac_reset(hw, port);
 
@@ -2250,9 +2242,14 @@ static void sky2_net_irq(struct net_device *dev, int enable)
 
 	u32 imask = sky2_read32(hw, B0_IMSK);
 	if (enable)
-		imask |= portirq_msk[sky2->port];
+		imask |= Y2_IS_BASE | portirq_msk[sky2->port];
 	else
 		imask &= ~portirq_msk[sky2->port];
+
+	/* Fully turn off interrupts if disabled for both ports */
+	if ((imask & ~Y2_IS_BASE) == 0)
+		imask = 0;
+
 	sky2_write32(hw, B0_IMSK, imask);
 }
 
@@ -2321,7 +2318,8 @@ static int sky2_probe(struct pci_device *pdev,
 		goto err_out_free_netdev;
 	}
 
-	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+	/* Disable interrupts by default */
+	sky2_write32(hw, B0_IMSK, 0);
 
 	sky2_show_addr(dev);
 
@@ -2370,8 +2368,6 @@ static void sky2_remove(struct pci_device *pdev)
 	for (i = hw->ports-1; i >= 0; --i)
 		unregister_netdev(hw->dev[i]);
 
-	sky2_write32(hw, B0_IMSK, 0);
-
 	sky2_power_aux(hw);
 
 	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
-- 
1.7.1



More information about the gPXE-devel mailing list