[RFT] skge: fiber carrier handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Does this fix your problems?  I don't have dual port boards but have an old SK-9843 fiber board.
====

The XM PHY can give IRQ on lost carrier, which is better than polling.
This version also solves an number of bonding/carrier related bugs.

Signed-off-by: Stephen Hemminger <[email protected]>

--- a/drivers/net/skge.c	2007-07-12 14:19:55.000000000 -0700
+++ b/drivers/net/skge.c	2007-07-12 14:53:39.000000000 -0700
@@ -1091,13 +1091,7 @@ static void xm_link_down(struct skge_hw 
 {
 	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);
-	}
+	u16 cmd;
 
 	cmd = xm_read16(hw, port, XM_MMU_CMD);
 	cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1107,6 +1101,10 @@ static void xm_link_down(struct skge_hw 
 
 	if (netif_carrier_ok(dev))
 		skge_link_down(skge);
+
+	/* If needed start polling for link to come up */
+	if (netif_running(dev) && hw->phy_type == SK_PHY_XMAC)
+		mod_timer(&skge->link_timer, jiffies + LINK_HZ);
 }
 
 static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
@@ -1434,30 +1432,25 @@ static void xm_phy_init(struct skge_port
 
 	xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
 
-	/* Poll PHY for status changes */
-	mod_timer(&skge->link_timer, jiffies + LINK_HZ);
+	/* Poll for link coming up */
+	mod_timer(&skge->link_timer, jiffies);
 }
 
-static void xm_check_link(struct net_device *dev)
+/* Check status of link and change state */
+static void xm_link_up(struct skge_port *skge)
 {
-	struct skge_port *skge = netdev_priv(dev);
+	struct net_device *dev = skge->netdev;
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
-	u16 status;
-
-	/* read twice because of latch */
-	(void) xm_phy_read(hw, port, PHY_XMAC_STAT);
-	status = xm_phy_read(hw, port, PHY_XMAC_STAT);
+	u16 isrc = xm_read16(hw, port, XM_ISRC);
 
-	if ((status & PHY_ST_LSYNC) == 0) {
-		xm_link_down(hw, port);
-		return;
-	}
+	if (netif_msg_intr(skge))
+		printk(KERN_DEBUG PFX "%s: fiber status %#x\n", dev->name, isrc);
 
 	if (skge->autoneg == AUTONEG_ENABLE) {
 		u16 lpa, res;
 
-		if (!(status & PHY_ST_AN_OVER))
+		if (!(isrc & XM_IS_AND))
 			return;
 
 		lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
@@ -1506,10 +1499,7 @@ static void xm_check_link(struct net_dev
 		genesis_link_up(skge);
 }
 
-/* Poll to check for link coming up.
- * Since internal PHY is wired to a level triggered pin, can't
- * get an interrupt when carrier is detected.
- */
+/* Poll to check for link coming up. */
 static void xm_link_timer(unsigned long arg)
 {
 	struct skge_port *skge = (struct skge_port *) arg;
@@ -1520,23 +1510,18 @@ static void xm_link_timer(unsigned long 
 	if (!netif_running(dev))
 		return;
 
-	if (netif_carrier_ok(dev)) {
-		xm_read16(hw, port, XM_ISRC);
-		if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS))
-			goto nochange;
-	} else {
-		if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
-			goto nochange;
-		xm_read16(hw, port, XM_ISRC);
-		if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
-			goto nochange;
-	}
+	if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+		goto resync;
 
 	spin_lock(&hw->phy_lock);
-	xm_check_link(dev);
+	xm_link_up(skge);
 	spin_unlock(&hw->phy_lock);
 
-nochange:
+	/* Link up, timer no longer needed */
+	if (netif_carrier_ok(dev))
+		return;
+
+resync:
 	if (netif_running(dev))
 		mod_timer(&skge->link_timer, jiffies + LINK_HZ);
 }
@@ -1593,6 +1578,9 @@ static void genesis_mac_init(struct skge
 		bcom_check_link(hw, port);
 	}
 
+	/* Clear any irq */
+	xm_read16(hw, port, XM_ISRC);
+
 	/* Set Station Address */
 	xm_outaddr(hw, port, XM_SA, dev->dev_addr);
 
@@ -1782,8 +1770,7 @@ static void genesis_mac_intr(struct skge
 		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)))
+	if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS))
 		xm_link_down(hw, port);
 
 	if (status & XM_IS_TXF_UR) {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux