[PATCH] skge: fix stuck irq when fiber down
Stephen Hemminger [Thu, 5 Oct 2006 22:49:50 +0000 (15:49 -0700)]
The PHY interrupt from the internal fiber is getting
stuck on when the link is down. Add code to handle the
transition and mask it.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

drivers/net/skge.c
drivers/net/skge.h

index a4a58e4..5776493 100644 (file)
@@ -884,6 +884,29 @@ static void skge_link_down(struct skge_port *skge)
                printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
 }
 
+
+static void xm_link_down(struct skge_hw *hw, int port)
+{
+       struct net_device *dev = hw->dev[port];
+       struct skge_port *skge = netdev_priv(dev);
+       u16 cmd, msk;
+
+       if (hw->phy_type == SK_PHY_XMAC) {
+               msk = xm_read16(hw, port, XM_IMSK);
+               msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND;
+               xm_write16(hw, port, XM_IMSK, msk);
+       }
+
+       cmd = xm_read16(hw, port, XM_MMU_CMD);
+       cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+       xm_write16(hw, port, XM_MMU_CMD, cmd);
+       /* dummy read to ensure writing */
+       (void) xm_read16(hw, port, XM_MMU_CMD);
+
+       if (netif_carrier_ok(dev))
+               skge_link_down(skge);
+}
+
 static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
 {
        int i;
@@ -1008,14 +1031,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
        status = xm_phy_read(hw, port, PHY_BCOM_STAT);
 
        if ((status & PHY_ST_LSYNC) == 0) {
-               u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
-               cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-               xm_write16(hw, port, XM_MMU_CMD, cmd);
-               /* dummy read to ensure writing */
-               (void) xm_read16(hw, port, XM_MMU_CMD);
-
-               if (netif_carrier_ok(dev))
-                       skge_link_down(skge);
+               xm_link_down(hw, port);
                return;
        }
 
@@ -1235,14 +1251,7 @@ static void xm_check_link(struct net_device *dev)
        status = xm_phy_read(hw, port, PHY_XMAC_STAT);
 
        if ((status & PHY_ST_LSYNC) == 0) {
-               u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
-               cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-               xm_write16(hw, port, XM_MMU_CMD, cmd);
-               /* dummy read to ensure writing */
-               (void) xm_read16(hw, port, XM_MMU_CMD);
-
-               if (netif_carrier_ok(dev))
-                       skge_link_down(skge);
+               xm_link_down(hw, port);
                return;
        }
 
@@ -1568,6 +1577,10 @@ static void genesis_mac_intr(struct skge_hw *hw, int port)
                printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
                       skge->netdev->name, status);
 
+       if (hw->phy_type == SK_PHY_XMAC &&
+           (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC)))
+               xm_link_down(hw, port);
+
        if (status & XM_IS_TXF_UR) {
                xm_write32(hw, port, XM_MODE, XM_MD_FTF);
                ++skge->net_stats.tx_fifo_errors;
@@ -1582,7 +1595,7 @@ static void genesis_link_up(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
-       u16 cmd;
+       u16 cmd, msk;
        u32 mode;
 
        cmd = xm_read16(hw, port, XM_MMU_CMD);
@@ -1631,7 +1644,11 @@ static void genesis_link_up(struct skge_port *skge)
        }
 
        xm_write32(hw, port, XM_MODE, mode);
-       xm_write16(hw, port, XM_IMSK, XM_DEF_MSK);
+       msk = XM_DEF_MSK;
+       if (hw->phy_type != SK_PHY_XMAC)
+               msk |= XM_IS_INP_ASS;   /* disable GP0 interrupt bit */
+
+       xm_write16(hw, port, XM_IMSK, msk);
        xm_read16(hw, port, XM_ISRC);
 
        /* get MMU Command Reg. */
index d0b47d4..9cc955c 100644 (file)
@@ -2195,7 +2195,8 @@ enum {
        XM_IS_RX_COMP   = 1<<0, /* Bit  0:      Frame Rx Complete */
 };
 
-#define XM_DEF_MSK     (~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR))
+#define XM_DEF_MSK     (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \
+                          XM_IS_RXF_OV | XM_IS_TXF_UR))
 
 
 /*     XM_HW_CFG       16 bit r/w      Hardware Config Register */