diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-10-05 18:49:50 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-10-11 04:06:08 -0400 |
commit | a1bc9b875be597cdf147db2748ba7ddc6b0f0fbe (patch) | |
tree | a4820b33026072c5a3e0fb1b8a1d1b37184fd286 /drivers/net/skge.c | |
parent | 647519100105fb4ddfe6455e820093999c08c4be (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/skge.c')
-rw-r--r-- | drivers/net/skge.c | 53 |
1 files changed, 35 insertions, 18 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 | |||
888 | static 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 | |||
887 | static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) | 910 | static 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. */ |