]> err.no Git - linux-2.6/blobdiff - drivers/net/skge.c
Merge /spare/repo/linux-2.6/
[linux-2.6] / drivers / net / skge.c
index 1ba0ab596abdb6463fa0b7c81e3d4e9ae043d116..d7c98515fdfdd55d91cdd3fb54b1ca252ce2ec09 100644 (file)
@@ -42,7 +42,7 @@
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "0.7"
+#define DRV_VERSION            "0.9"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
@@ -55,7 +55,7 @@
 #define ETH_JUMBO_MTU          9000
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
-#define BLINK_HZ               (HZ/4)
+#define BLINK_MS               250
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -75,13 +75,12 @@ static const struct pci_device_id skge_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
-       { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx  */
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
        { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
-       { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) },
        { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
+       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -190,7 +189,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
 {
        u32 supported;
 
-       if (iscopper(hw)) {
+       if (hw->copper) {
                supported = SUPPORTED_10baseT_Half
                        | SUPPORTED_10baseT_Full
                        | SUPPORTED_100baseT_Half
@@ -223,7 +222,7 @@ static int skge_get_settings(struct net_device *dev,
        ecmd->transceiver = XCVR_INTERNAL;
        ecmd->supported = skge_supported_modes(hw);
 
-       if (iscopper(hw)) {
+       if (hw->copper) {
                ecmd->port = PORT_TP;
                ecmd->phy_address = hw->phy_addr;
        } else
@@ -249,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        } else {
                u32 setting;
 
-               switch(ecmd->speed) {
+               switch (ecmd->speed) {
                case SPEED_1000:
                        if (ecmd->duplex == DUPLEX_FULL)
                                setting = SUPPORTED_1000baseT_Full;
@@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev,
        return 0;
 }
 
-static void skge_led_on(struct skge_hw *hw, int port)
+enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST };
+static void skge_led(struct skge_port *skge, enum led_mode mode)
 {
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+
+       spin_lock_bh(&hw->phy_lock);
        if (hw->chip_id == CHIP_ID_GENESIS) {
-               skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
-               skge_write8(hw, B0_LED, LED_STAT_ON);
+               switch (mode) {
+               case LED_MODE_OFF:
+                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+                       skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
+                       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+                       break;
 
-               skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
-               skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
-               skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+               case LED_MODE_ON:
+                       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
+                       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
 
-               /* For Broadcom Phy only */
-               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
-       } else {
-               gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER,
-                                 PHY_M_LED_MO_DUP(MO_LED_ON)  |
-                                 PHY_M_LED_MO_10(MO_LED_ON)   |
-                                 PHY_M_LED_MO_100(MO_LED_ON)  |
-                                 PHY_M_LED_MO_1000(MO_LED_ON) |
-                                 PHY_M_LED_MO_RX(MO_LED_ON));
-       }
-}
+                       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+                       skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
 
-static void skge_led_off(struct skge_hw *hw, int port)
-{
-       if (hw->chip_id == CHIP_ID_GENESIS) {
-               skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
-               skge_write8(hw, B0_LED, LED_STAT_OFF);
+                       break;
 
-               skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
-               skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+               case LED_MODE_TST:
+                       skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
+                       skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
+                       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
 
-               /* Broadcom only */
-               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+                       break;
+               }
        } else {
-               gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER,
-                                 PHY_M_LED_MO_DUP(MO_LED_OFF)  |
-                                 PHY_M_LED_MO_10(MO_LED_OFF)   |
-                                 PHY_M_LED_MO_100(MO_LED_OFF)  |
-                                 PHY_M_LED_MO_1000(MO_LED_OFF) |
-                                 PHY_M_LED_MO_RX(MO_LED_OFF));
+               switch (mode) {
+               case LED_MODE_OFF:
+                       gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+                       gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+                                    PHY_M_LED_MO_DUP(MO_LED_OFF)  |
+                                    PHY_M_LED_MO_10(MO_LED_OFF)   |
+                                    PHY_M_LED_MO_100(MO_LED_OFF)  |
+                                    PHY_M_LED_MO_1000(MO_LED_OFF) |
+                                    PHY_M_LED_MO_RX(MO_LED_OFF));
+                       break;
+               case LED_MODE_ON:
+                       gm_phy_write(hw, port, PHY_MARV_LED_CTRL,
+                                    PHY_M_LED_PULS_DUR(PULS_170MS) |
+                                    PHY_M_LED_BLINK_RT(BLINK_84MS) |
+                                    PHY_M_LEDC_TX_CTRL |
+                                    PHY_M_LEDC_DP_CTRL);
+               
+                       gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+                                    PHY_M_LED_MO_RX(MO_LED_OFF) |
+                                    (skge->speed == SPEED_100 ?
+                                     PHY_M_LED_MO_100(MO_LED_ON) : 0));
+                       break;
+               case LED_MODE_TST:
+                       gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+                       gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+                                    PHY_M_LED_MO_DUP(MO_LED_ON)  |
+                                    PHY_M_LED_MO_10(MO_LED_ON)   |
+                                    PHY_M_LED_MO_100(MO_LED_ON)  |
+                                    PHY_M_LED_MO_1000(MO_LED_ON) |
+                                    PHY_M_LED_MO_RX(MO_LED_ON));
+               }
        }
-}
-
-static void skge_blink_timer(unsigned long data)
-{
-       struct skge_port *skge = (struct skge_port *) data;
-       struct skge_hw *hw = skge->hw;
-       unsigned long flags;
-
-       spin_lock_irqsave(&hw->phy_lock, flags);
-       if (skge->blink_on)
-               skge_led_on(hw, skge->port);
-       else
-               skge_led_off(hw, skge->port);
-       spin_unlock_irqrestore(&hw->phy_lock, flags);
-
-       skge->blink_on = !skge->blink_on;
-       mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
+       spin_unlock_bh(&hw->phy_lock);
 }
 
 /* blink LED's for finding board */
 static int skge_phys_id(struct net_device *dev, u32 data)
 {
        struct skge_port *skge = netdev_priv(dev);
+       unsigned long ms;
+       enum led_mode mode = LED_MODE_TST;
 
        if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-               data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+               ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000;
+       else
+               ms = data * 1000;
 
-       /* start blinking */
-       skge->blink_on = 1;
-       mod_timer(&skge->led_blink, jiffies+1);
+       while (ms > 0) {
+               skge_led(skge, mode);
+               mode ^= LED_MODE_TST;
 
-       msleep_interruptible(data * 1000);
-       del_timer_sync(&skge->led_blink);
+               if (msleep_interruptible(BLINK_MS))
+                       break;
+               ms -= BLINK_MS;
+       }
 
-       skge_led_off(skge->hw, skge->port);
+       /* back to regular LED state */
+       skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF);
 
        return 0;
 }
@@ -863,6 +876,9 @@ static int skge_rx_fill(struct skge_port *skge)
 
 static void skge_link_up(struct skge_port *skge)
 {
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), 
+                   LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+
        netif_carrier_on(skge->netdev);
        if (skge->tx_avail > MAX_SKB_FRAGS + 1)
                netif_wake_queue(skge->netdev);
@@ -881,6 +897,7 @@ static void skge_link_up(struct skge_port *skge)
 
 static void skge_link_down(struct skge_port *skge)
 {
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
        netif_carrier_off(skge->netdev);
        netif_stop_queue(skge->netdev);
 
@@ -1028,7 +1045,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
                        }
 
                        /* Check Duplex mismatch */
-                       switch(aux & PHY_B_AS_AN_RES_MSK) {
+                       switch (aux & PHY_B_AS_AN_RES_MSK) {
                        case PHY_B_RES_1000FD:
                                skge->duplex = DUPLEX_FULL;
                                break;
@@ -1099,7 +1116,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
        r |=  XM_MMU_NO_PRE;
        xm_write16(hw, port, XM_MMU_CMD,r);
 
-       switch(id1) {
+       switch (id1) {
        case PHY_BCOM_ID1_C0:
                /*
                 * Workaround BCOM Errata for the C0 type.
@@ -1194,13 +1211,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
        xm_write16(hw, port, XM_STAT_CMD,
                        XM_SC_CLR_RXC | XM_SC_CLR_TXC);
 
-       /* initialize Rx, Tx and Link LED */
-       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
-       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
-
-       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
-       skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
-
        /* Unreset the XMAC. */
        skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
 
@@ -1209,7 +1219,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
         * namely for the 1000baseTX cards that use the XMAC's
         * GMII mode.
         */
-       spin_lock_bh(&hw->phy_lock);
        /* Take external Phy out of reset */
        r = skge_read32(hw, B2_GP_IO);
        if (port == 0)
@@ -1219,7 +1228,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
 
        skge_write32(hw, B2_GP_IO, r);
        skge_read32(hw, B2_GP_IO);
-       spin_unlock_bh(&hw->phy_lock);
 
        /* Enable GMII interfac */
        xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
@@ -1569,7 +1577,6 @@ static void yukon_init(struct skge_hw *hw, int port)
 {
        struct skge_port *skge = netdev_priv(hw->dev[port]);
        u16 ctrl, ct1000, adv;
-       u16 ledctrl, ledover;
 
        pr_debug("yukon_init\n");
        if (skge->autoneg == AUTONEG_ENABLE) {
@@ -1596,7 +1603,7 @@ static void yukon_init(struct skge_hw *hw, int port)
        adv = PHY_AN_CSMA;
 
        if (skge->autoneg == AUTONEG_ENABLE) {
-               if (iscopper(hw)) {
+               if (hw->copper) {
                        if (skge->advertising & ADVERTISED_1000baseT_Full)
                                ct1000 |= PHY_M_1000C_AFD;
                        if (skge->advertising & ADVERTISED_1000baseT_Half)
@@ -1641,32 +1648,11 @@ static void yukon_init(struct skge_hw *hw, int port)
        gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
        gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
 
-       /* Setup Phy LED's */
-       ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
-       ledover = 0;
-
-       ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
-
-       /* turn off the Rx LED (LED_RX) */
-       ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
-
-       /* disable blink mode (LED_DUPLEX) on collisions */
-       ctrl |= PHY_M_LEDC_DP_CTRL;
-       gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
-
-       if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
-               /* turn on 100 Mbps LED (LED_LINK100) */
-               ledover |= PHY_M_LED_MO_100(MO_LED_ON);
-       }
-
-       if (ledover)
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
-
        /* Enable phy interrupt on autonegotiation complete (or link up) */
        if (skge->autoneg == AUTONEG_ENABLE)
-               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK);
        else
-               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
 }
 
 static void yukon_reset(struct skge_hw *hw, int port)
@@ -1691,7 +1677,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
 
        /* WA code for COMA mode -- set PHY reset */
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3)
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
                skge_write32(hw, B2_GP_IO,
                             (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
 
@@ -1701,7 +1687,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
 
        /* WA code for COMA mode -- clear PHY reset */
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3)
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
                skge_write32(hw, B2_GP_IO,
                             (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
                             & ~GP_IO_9);
@@ -1709,7 +1695,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        /* Set hardware config mode */
        reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
                GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
-       reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+       reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
 
        /* Clear GMC reset */
        skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
@@ -1745,9 +1731,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        gma_write16(hw, port, GM_GP_CTRL, reg);
        skge_read16(hw, GMAC_IRQ_SRC);
 
-       spin_lock_bh(&hw->phy_lock);
        yukon_init(hw, port);
-       spin_unlock_bh(&hw->phy_lock);
 
        /* MIB clear */
        reg = gma_read16(hw, port, GM_PHY_ADDR);
@@ -1796,11 +1780,16 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
        reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3)
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
                reg &= ~GMF_RX_F_FL_ON;
        skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
        skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
-       skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+       /*
+        * because Pause Packet Truncation in GMAC is not working
+        * we have to increase the Flush Threshold to 64 bytes
+        * in order to flush pause packets in Rx FIFO on Yukon-1
+        */
+       skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
 
        /* Configure Tx MAC FIFO */
        skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1813,19 +1802,19 @@ static void yukon_stop(struct skge_port *skge)
        int port = skge->port;
 
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3) {
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
                skge_write32(hw, B2_GP_IO,
                             skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
        }
 
        gma_write16(hw, port, GM_GP_CTRL,
                         gma_read16(hw, port, GM_GP_CTRL)
-                        & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
+                        & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
        gma_read16(hw, port, GM_GP_CTRL);
 
        /* set GPHY Control reset */
-       gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
-       gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+       skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+       skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
 }
 
 static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1856,11 +1845,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port)
 
        if (status & GM_IS_RX_FF_OR) {
                ++skge->net_stats.rx_fifo_errors;
-               gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+               skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
        }
+
        if (status & GM_IS_TX_FF_UR) {
                ++skge->net_stats.tx_fifo_errors;
-               gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+               skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
        }
 
 }
@@ -1896,7 +1886,7 @@ static void yukon_link_up(struct skge_port *skge)
        reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
        gma_write16(hw, port, GM_GP_CTRL, reg);
 
-       gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+       gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
        skge_link_up(skge);
 }
 
@@ -1904,12 +1894,14 @@ static void yukon_link_down(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
+       u16 ctrl;
 
        pr_debug("yukon_link_down\n");
        gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
-       gm_phy_write(hw, port, GM_GP_CTRL,
-                         gm_phy_read(hw, port, GM_GP_CTRL)
-                         & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+       ctrl = gma_read16(hw, port, GM_GP_CTRL);
+       ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+       gma_write16(hw, port, GM_GP_CTRL, ctrl);
 
        if (skge->flow_control == FLOW_MODE_REM_SEND) {
                /* restore Asymmetric Pause bit */
@@ -2097,10 +2089,12 @@ static int skge_up(struct net_device *dev)
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
        /* Initialze MAC */
+       spin_lock_bh(&hw->phy_lock);
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_mac_init(hw, port);
        else
                yukon_mac_init(hw, port);
+       spin_unlock_bh(&hw->phy_lock);
 
        /* Configure RAMbuffers */
        chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2116,6 +2110,7 @@ static int skge_up(struct net_device *dev)
        /* Start receiver BMU */
        wmb();
        skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+       skge_led(skge, LED_MODE_ON);
 
        pr_debug("skge_up completed\n");
        return 0;
@@ -2140,8 +2135,6 @@ static int skge_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       del_timer_sync(&skge->led_blink);
-
        /* Stop transmitter */
        skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
        skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
@@ -2175,15 +2168,12 @@ static int skge_down(struct net_device *dev)
        if (hw->chip_id == CHIP_ID_GENESIS) {
                skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
                skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
-               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP);
-               skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP);
        } else {
                skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
                skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
        }
 
-       /* turn off led's */
-       skge_write16(hw, B0_LED, LED_STAT_OFF);
+       skge_led(skge, LED_MODE_OFF);
 
        skge_tx_clean(skge);
        skge_rx_clean(skge);
@@ -2689,18 +2679,6 @@ static void skge_error_irq(struct skge_hw *hw)
                /* Timestamp (unused) overflow */
                if (hwstatus & IS_IRQ_TIST_OV)
                        skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
-
-               if (hwstatus & IS_IRQ_SENSOR) {
-                       /* no sensors on 32-bit Yukon */
-                       if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
-                               printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
-                               skge_write32(hw, B0_HWE_IMSK,
-                                            IS_ERR_MSK & ~IS_IRQ_SENSOR);
-                       } else
-                               printk(KERN_WARNING PFX "sensor interrupt\n");
-               }
-
-
        }
 
        if (hwstatus & IS_RAM_RD_PAR) {
@@ -2731,9 +2709,10 @@ static void skge_error_irq(struct skge_hw *hw)
 
                skge_pci_clear(hw);
 
+               /* if error still set then just ignore it */
                hwstatus = skge_read32(hw, B0_HWE_ISRC);
                if (hwstatus & IS_IRQ_STAT) {
-                       printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+                       pr_debug("IRQ status %x: still set ignoring hardware errors\n",
                               hwstatus);
                        hw->intr_mask &= ~IS_HW_ERR;
                }
@@ -2895,7 +2874,7 @@ static const char *skge_board_name(const struct skge_hw *hw)
 static int skge_reset(struct skge_hw *hw)
 {
        u16 ctst;
-       u8 t8, mac_cfg;
+       u8 t8, mac_cfg, pmd_type, phy_type;
        int i;
 
        ctst = skge_read16(hw, B0_CTST);
@@ -2914,18 +2893,19 @@ static int skge_reset(struct skge_hw *hw)
                     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
 
        hw->chip_id = skge_read8(hw, B2_CHIP_ID);
-       hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
-       hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+       phy_type = skge_read8(hw, B2_E_1) & 0xf;
+       pmd_type = skge_read8(hw, B2_PMD_TYP);
+       hw->copper = (pmd_type == 'T' || pmd_type == '1');
 
        switch (hw->chip_id) {
        case CHIP_ID_GENESIS:
-               switch (hw->phy_type) {
+               switch (phy_type) {
                case SK_PHY_BCOM:
                        hw->phy_addr = PHY_ADDR_BCOM;
                        break;
                default:
                        printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
-                              pci_name(hw->pdev), hw->phy_type);
+                              pci_name(hw->pdev), phy_type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -2933,13 +2913,10 @@ static int skge_reset(struct skge_hw *hw)
        case CHIP_ID_YUKON:
        case CHIP_ID_YUKON_LITE:
        case CHIP_ID_YUKON_LP:
-               if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
-                       hw->phy_type = SK_PHY_MARV_COPPER;
+               if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+                       hw->copper = 1;
 
                hw->phy_addr = PHY_ADDR_MARV;
-               if (!iscopper(hw))
-                       hw->phy_type = SK_PHY_MARV_FIBER;
-
                break;
 
        default:
@@ -2967,12 +2944,20 @@ static int skge_reset(struct skge_hw *hw)
        else
                hw->ram_size = t8 * 4096;
 
+       hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_init(hw);
        else {
                /* switch power to VCC (WA for VAUX problem) */
                skge_write8(hw, B0_POWER_CTRL,
                            PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+               /* avoid boards with stuck Hardware error bits */
+               if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) &&
+                   (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) {
+                       printk(KERN_WARNING PFX "stuck hardware sensor bit\n");
+                       hw->intr_mask &= ~IS_HW_ERR;
+               }
+
                for (i = 0; i < hw->ports; i++) {
                        skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
                        skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
@@ -3013,7 +2998,6 @@ static int skge_reset(struct skge_hw *hw)
        skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
        skge_write32(hw, B2_IRQM_CTRL, TIM_START);
 
-       hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
        if (hw->chip_id != CHIP_ID_GENESIS)
@@ -3089,10 +3073,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        spin_lock_init(&skge->tx_lock);
 
-       init_timer(&skge->led_blink);
-       skge->led_blink.function = skge_blink_timer;
-       skge->led_blink.data = (unsigned long) skge;
-
        if (hw->chip_id != CHIP_ID_GENESIS) {
                dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                skge->rx_csum = 1;