-stable review patch.  If anyone has any objections, please let us know.

------------------
From: Stephen Hemminger <[EMAIL PROTECTED]>

patch 501fb72d052d2a302b423bef7dec98d9d98c8a36 in mainline.

Change how PHY is managed on SysKonnect fibre based boards.
Poll for PHY coming up 1 per second, but use interrupt to detect loss.

Signed-off-by: Stephen Hemminger <[EMAIL PROTECTED]>
Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
 drivers/net/skge.c |   90 ++++++++++++++++++++++++++++-------------------------
 drivers/net/skge.h |    6 +--
 2 files changed, 51 insertions(+), 45 deletions(-)

--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -57,7 +57,7 @@
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
 #define BLINK_MS               250
-#define LINK_HZ                        (HZ/2)
+#define LINK_HZ                        HZ
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <[EMAIL PROTECTED]>");
@@ -992,19 +992,15 @@ 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;
+       u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
 
-       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);
-       }
+       xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
 
-       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);
+       xm_read16(hw, port, XM_MMU_CMD);
 
        if (netif_carrier_ok(dev))
                skge_link_down(skge);
@@ -1100,7 +1096,7 @@ static void genesis_reset(struct skge_hw
 
        /* reset the statistics module */
        xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
-       xm_write16(hw, port, XM_IMSK, 0xffff);  /* disable XMAC IRQs */
+       xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
        xm_write32(hw, port, XM_MODE, 0);               /* clear Mode Reg */
        xm_write16(hw, port, XM_TX_CMD, 0);     /* reset TX CMD Reg */
        xm_write16(hw, port, XM_RX_CMD, 0);     /* reset RX CMD Reg */
@@ -1138,7 +1134,7 @@ static void bcom_check_link(struct skge_
        u16 status;
 
        /* read twice because of latch */
-       (void) xm_phy_read(hw, port, PHY_BCOM_STAT);
+       xm_phy_read(hw, port, PHY_BCOM_STAT);
        status = xm_phy_read(hw, port, PHY_BCOM_STAT);
 
        if ((status & PHY_ST_LSYNC) == 0) {
@@ -1339,7 +1335,7 @@ static void xm_phy_init(struct skge_port
        mod_timer(&skge->link_timer, jiffies + LINK_HZ);
 }
 
-static void xm_check_link(struct net_device *dev)
+static int xm_check_link(struct net_device *dev)
 {
        struct skge_port *skge = netdev_priv(dev);
        struct skge_hw *hw = skge->hw;
@@ -1347,25 +1343,25 @@ static void xm_check_link(struct net_dev
        u16 status;
 
        /* read twice because of latch */
-       (void) xm_phy_read(hw, port, PHY_XMAC_STAT);
+       xm_phy_read(hw, port, PHY_XMAC_STAT);
        status = xm_phy_read(hw, port, PHY_XMAC_STAT);
 
        if ((status & PHY_ST_LSYNC) == 0) {
                xm_link_down(hw, port);
-               return;
+               return 0;
        }
 
        if (skge->autoneg == AUTONEG_ENABLE) {
                u16 lpa, res;
 
                if (!(status & PHY_ST_AN_OVER))
-                       return;
+                       return 0;
 
                lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
                if (lpa & PHY_B_AN_RF) {
                        printk(KERN_NOTICE PFX "%s: remote fault\n",
                               dev->name);
-                       return;
+                       return 0;
                }
 
                res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
@@ -1381,7 +1377,7 @@ static void xm_check_link(struct net_dev
                default:
                        printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
                               dev->name);
-                       return;
+                       return 0;
                }
 
                /* We are using IEEE 802.3z/D5.0 Table 37-4 */
@@ -1405,11 +1401,14 @@ static void xm_check_link(struct net_dev
 
        if (!netif_carrier_ok(dev))
                genesis_link_up(skge);
+       return 1;
 }
 
 /* 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.
+ * get an interrupt when carrier is detected, need to poll for
+ * link coming up.
  */
 static void xm_link_timer(unsigned long arg)
 {
@@ -1417,29 +1416,35 @@ static void xm_link_timer(unsigned long 
        struct net_device *dev = skge->netdev;
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
+       int i;
+       unsigned long flags;
 
        if (!netif_running(dev))
                return;
 
-       if (netif_carrier_ok(dev)) {
+       spin_lock_irqsave(&hw->phy_lock, flags);
+
+       /*
+        * Verify that the link by checking GPIO register three times.
+        * This pin has the signal from the link_sync pin connected to it.
+        */
+       for (i = 0; i < 3; i++) {
+               if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+                       goto link_down;
+       }
+
+        /* Re-enable interrupt to detect link down */
+       if (xm_check_link(dev)) {
+               u16 msk = xm_read16(hw, port, XM_IMSK);
+               msk &= ~XM_IS_INP_ASS;
+               xm_write16(hw, port, XM_IMSK, msk);
                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;
+link_down:
+               mod_timer(&skge->link_timer,
+                         round_jiffies(jiffies + LINK_HZ));
        }
-
-       spin_lock(&hw->phy_lock);
-       xm_check_link(dev);
-       spin_unlock(&hw->phy_lock);
-
-nochange:
-       if (netif_running(dev))
-               mod_timer(&skge->link_timer, jiffies + LINK_HZ);
+       spin_unlock_irqrestore(&hw->phy_lock, flags);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -1683,14 +1688,16 @@ 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)))
-               xm_link_down(hw, port);
+       if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) {
+               xm_link_down(hw, port);
+               mod_timer(&skge->link_timer, jiffies + 1);
+       }
 
        if (status & XM_IS_TXF_UR) {
                xm_write32(hw, port, XM_MODE, XM_MD_FTF);
                ++skge->net_stats.tx_fifo_errors;
        }
+
        if (status & XM_IS_RXF_OV) {
                xm_write32(hw, port, XM_MODE, XM_MD_FRF);
                ++skge->net_stats.rx_fifo_errors;
@@ -1750,11 +1757,12 @@ static void genesis_link_up(struct skge_
        }
 
        xm_write32(hw, port, XM_MODE, mode);
-       msk = XM_DEF_MSK;
-       if (hw->phy_type != SK_PHY_XMAC)
-               msk |= XM_IS_INP_ASS;   /* disable GP0 interrupt bit */
 
+       /* Turn on detection of Tx underrun, Rx overrun */
+       msk = xm_read16(hw, port, XM_IMSK);
+       msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR);
        xm_write16(hw, port, XM_IMSK, msk);
+
        xm_read16(hw, port, XM_ISRC);
 
        /* get MMU Command Reg. */
@@ -2185,7 +2193,7 @@ static void yukon_mac_intr(struct skge_h
        u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
 
        if (netif_msg_intr(skge))
-               printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
+               printk(KERN_DEBUG PFX "%s: yukon mac interrupt status 0x%x\n",
                       dev->name, status);
 
        if (status & GM_IS_RX_FF_OR) {
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2193,11 +2193,9 @@ enum {
        XM_IS_TXF_UR    = 1<<2, /* Bit  2:      Transmit FIFO Underrun */
        XM_IS_TX_COMP   = 1<<1, /* Bit  1:      Frame Tx Complete */
        XM_IS_RX_COMP   = 1<<0, /* Bit  0:      Frame Rx Complete */
-};
-
-#define XM_DEF_MSK     (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \
-                          XM_IS_RXF_OV | XM_IS_TXF_UR))
 
+       XM_IMSK_DISABLE = 0xffff,
+};
 
 /*     XM_HW_CFG       16 bit r/w      Hardware Config Register */
 enum {

-- 
-
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/

Reply via email to