aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-10-05 18:49:50 -0400
committerJeff Garzik <jeff@garzik.org>2006-10-11 04:06:08 -0400
commita1bc9b875be597cdf147db2748ba7ddc6b0f0fbe (patch)
treea4820b33026072c5a3e0fb1b8a1d1b37184fd286 /drivers/net
parent647519100105fb4ddfe6455e820093999c08c4be (diff)
[PATCH] skge: fix stuck irq when fiber down
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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/skge.c53
-rw-r--r--drivers/net/skge.h3
2 files changed, 37 insertions, 19 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index a4a58e4e93a1..57764935a9f8 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -884,6 +884,29 @@ static void skge_link_down(struct skge_port *skge)
884 printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); 884 printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
885} 885}
886 886
887
888static void xm_link_down(struct skge_hw *hw, int port)
889{
890 struct net_device *dev = hw->dev[port];
891 struct skge_port *skge = netdev_priv(dev);
892 u16 cmd, msk;
893
894 if (hw->phy_type == SK_PHY_XMAC) {
895 msk = xm_read16(hw, port, XM_IMSK);
896 msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND;
897 xm_write16(hw, port, XM_IMSK, msk);
898 }
899
900 cmd = xm_read16(hw, port, XM_MMU_CMD);
901 cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
902 xm_write16(hw, port, XM_MMU_CMD, cmd);
903 /* dummy read to ensure writing */
904 (void) xm_read16(hw, port, XM_MMU_CMD);
905
906 if (netif_carrier_ok(dev))
907 skge_link_down(skge);
908}
909
887static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) 910static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
888{ 911{
889 int i; 912 int i;
@@ -1008,14 +1031,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
1008 status = xm_phy_read(hw, port, PHY_BCOM_STAT); 1031 status = xm_phy_read(hw, port, PHY_BCOM_STAT);
1009 1032
1010 if ((status & PHY_ST_LSYNC) == 0) { 1033 if ((status & PHY_ST_LSYNC) == 0) {
1011 u16 cmd = xm_read16(hw, port, XM_MMU_CMD); 1034 xm_link_down(hw, port);
1012 cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
1013 xm_write16(hw, port, XM_MMU_CMD, cmd);
1014 /* dummy read to ensure writing */
1015 (void) xm_read16(hw, port, XM_MMU_CMD);
1016
1017 if (netif_carrier_ok(dev))
1018 skge_link_down(skge);
1019 return; 1035 return;
1020 } 1036 }
1021 1037
@@ -1235,14 +1251,7 @@ static void xm_check_link(struct net_device *dev)
1235 status = xm_phy_read(hw, port, PHY_XMAC_STAT); 1251 status = xm_phy_read(hw, port, PHY_XMAC_STAT);
1236 1252
1237 if ((status & PHY_ST_LSYNC) == 0) { 1253 if ((status & PHY_ST_LSYNC) == 0) {
1238 u16 cmd = xm_read16(hw, port, XM_MMU_CMD); 1254 xm_link_down(hw, port);
1239 cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
1240 xm_write16(hw, port, XM_MMU_CMD, cmd);
1241 /* dummy read to ensure writing */
1242 (void) xm_read16(hw, port, XM_MMU_CMD);
1243
1244 if (netif_carrier_ok(dev))
1245 skge_link_down(skge);
1246 return; 1255 return;
1247 } 1256 }
1248 1257
@@ -1568,6 +1577,10 @@ static void genesis_mac_intr(struct skge_hw *hw, int port)
1568 printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", 1577 printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
1569 skge->netdev->name, status); 1578 skge->netdev->name, status);
1570 1579
1580 if (hw->phy_type == SK_PHY_XMAC &&
1581 (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC)))
1582 xm_link_down(hw, port);
1583
1571 if (status & XM_IS_TXF_UR) { 1584 if (status & XM_IS_TXF_UR) {
1572 xm_write32(hw, port, XM_MODE, XM_MD_FTF); 1585 xm_write32(hw, port, XM_MODE, XM_MD_FTF);
1573 ++skge->net_stats.tx_fifo_errors; 1586 ++skge->net_stats.tx_fifo_errors;
@@ -1582,7 +1595,7 @@ static void genesis_link_up(struct skge_port *skge)
1582{ 1595{
1583 struct skge_hw *hw = skge->hw; 1596 struct skge_hw *hw = skge->hw;
1584 int port = skge->port; 1597 int port = skge->port;
1585 u16 cmd; 1598 u16 cmd, msk;
1586 u32 mode; 1599 u32 mode;
1587 1600
1588 cmd = xm_read16(hw, port, XM_MMU_CMD); 1601 cmd = xm_read16(hw, port, XM_MMU_CMD);
@@ -1631,7 +1644,11 @@ static void genesis_link_up(struct skge_port *skge)
1631 } 1644 }
1632 1645
1633 xm_write32(hw, port, XM_MODE, mode); 1646 xm_write32(hw, port, XM_MODE, mode);
1634 xm_write16(hw, port, XM_IMSK, XM_DEF_MSK); 1647 msk = XM_DEF_MSK;
1648 if (hw->phy_type != SK_PHY_XMAC)
1649 msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */
1650
1651 xm_write16(hw, port, XM_IMSK, msk);
1635 xm_read16(hw, port, XM_ISRC); 1652 xm_read16(hw, port, XM_ISRC);
1636 1653
1637 /* get MMU Command Reg. */ 1654 /* get MMU Command Reg. */
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index d0b47d46cf9d..9cc955c12503 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2195,7 +2195,8 @@ enum {
2195 XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */ 2195 XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */
2196}; 2196};
2197 2197
2198#define XM_DEF_MSK (~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR)) 2198#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \
2199 XM_IS_RXF_OV | XM_IS_TXF_UR))
2199 2200
2200 2201
2201/* XM_HW_CFG 16 bit r/w Hardware Config Register */ 2202/* XM_HW_CFG 16 bit r/w Hardware Config Register */