Merge /spare/repo/linux-2.6/
[deliverable/linux.git] / drivers / net / skge.c
index f15739481d628f641850bb1b46f9a8b31f62263f..7ce734ec6ba8c94f5ebcb4cb4aebbfef3f926a21 100644 (file)
@@ -42,7 +42,7 @@
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "0.8"
+#define DRV_VERSION            "1.0"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
@@ -79,8 +79,8 @@ static const struct pci_device_id skge_id_table[] = {
        { 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);
@@ -189,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
@@ -222,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
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
                                     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 ?
@@ -743,6 +743,7 @@ static struct ethtool_ops skge_ethtool_ops = {
        .phys_id        = skge_phys_id,
        .get_stats_count = skge_get_stats_count,
        .get_ethtool_stats = skge_get_ethtool_stats,
+       .get_perm_addr  = ethtool_op_get_perm_addr,
 };
 
 /*
@@ -876,6 +877,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);
@@ -894,6 +898,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);
 
@@ -983,6 +988,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
 {
        const u8 zero[8]  = { 0 };
 
+       skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
        /* 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 */
@@ -1017,8 +1024,6 @@ static void bcom_check_link(struct skge_hw *hw, int port)
        (void) xm_phy_read(hw, port, PHY_BCOM_STAT);
        status = xm_phy_read(hw, port, PHY_BCOM_STAT);
 
-       pr_debug("bcom_check_link status=0x%x\n", status);
-
        if ((status & PHY_ST_LSYNC) == 0) {
                u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
                cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1102,8 +1107,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
                { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
        };
 
-       pr_debug("bcom_phy_init\n");
-
        /* read Id from external PHY (all have the same address) */
        id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
 
@@ -1336,6 +1339,8 @@ static void genesis_stop(struct skge_port *skge)
        int port = skge->port;
        u32 reg;
 
+       genesis_reset(hw, port);
+
        /* Clear Tx packet arbiter timeout IRQ */
        skge_write16(hw, B3_PA_CTRL,
                     port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@@ -1461,7 +1466,6 @@ static void genesis_link_up(struct skge_port *skge)
        u16 cmd;
        u32 mode, msk;
 
-       pr_debug("genesis_link_up\n");
        cmd = xm_read16(hw, port, XM_MMU_CMD);
 
        /*
@@ -1574,7 +1578,6 @@ static void yukon_init(struct skge_hw *hw, int port)
        struct skge_port *skge = netdev_priv(hw->dev[port]);
        u16 ctrl, ct1000, adv;
 
-       pr_debug("yukon_init\n");
        if (skge->autoneg == AUTONEG_ENABLE) {
                u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
 
@@ -1599,7 +1602,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)
@@ -1673,9 +1676,11 @@ 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)
-               skge_write32(hw, B2_GP_IO,
-                            (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+               reg = skge_read32(hw, B2_GP_IO);
+               reg |= GP_DIR_9 | GP_IO_9;
+               skge_write32(hw, B2_GP_IO, reg);
+       }
 
        /* hard reset */
        skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@@ -1683,15 +1688,17 @@ 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)
-               skge_write32(hw, B2_GP_IO,
-                            (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
-                            & ~GP_IO_9);
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+               reg = skge_read32(hw, B2_GP_IO);
+               reg |= GP_DIR_9;
+               reg &= ~GP_IO_9;
+               skge_write32(hw, B2_GP_IO, reg);
+       }
 
        /* 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);
@@ -1725,7 +1732,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);
+       skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
 
        yukon_init(hw, port);
 
@@ -1780,7 +1787,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
                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);
@@ -1792,20 +1804,26 @@ static void yukon_stop(struct skge_port *skge)
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
 
-       if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           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);
-       }
+       skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+       yukon_reset(hw, port);
 
        gma_write16(hw, port, GM_GP_CTRL,
                         gma_read16(hw, port, GM_GP_CTRL)
                         & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
        gma_read16(hw, port, GM_GP_CTRL);
 
+       if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+               u32 io = skge_read32(hw, B2_GP_IO);
+
+               io |= GP_DIR_9 | GP_IO_9;
+               skge_write32(hw, B2_GP_IO, io);
+               skge_read32(hw, B2_GP_IO);
+       }
+
        /* set GPHY Control reset */
-       skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
-       skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+       skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+       skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
 }
 
 static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1864,10 +1882,8 @@ static void yukon_link_up(struct skge_port *skge)
        int port = skge->port;
        u16 reg;
 
-       pr_debug("yukon_link_up\n");
-
        /* Enable Transmit FIFO Underrun */
-       skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+       skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
 
        reg = gma_read16(hw, port, GM_GP_CTRL);
        if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@@ -1887,7 +1903,6 @@ static void yukon_link_down(struct skge_port *skge)
        int port = skge->port;
        u16 ctrl;
 
-       pr_debug("yukon_link_down\n");
        gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
 
        ctrl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2103,7 +2118,6 @@ static int skge_up(struct net_device *dev)
        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;
 
  free_rx_ring:
@@ -2126,15 +2140,20 @@ static int skge_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+       if (hw->chip_id == CHIP_ID_GENESIS)
+               genesis_stop(skge);
+       else
+               yukon_stop(skge);
+
+       hw->intr_mask &= ~portirqmask[skge->port];
+       skge_write32(hw, B0_IMSK, hw->intr_mask);
+
        /* Stop transmitter */
        skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
        skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
                     RB_RST_SET|RB_DIS_OP_MD);
 
-       if (hw->chip_id == CHIP_ID_GENESIS)
-               genesis_stop(skge);
-       else
-               yukon_stop(skge);
 
        /* Disable Force Sync bit and Enable Alloc bit */
        skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2358,8 +2377,6 @@ static void genesis_set_multicast(struct net_device *dev)
        u32 mode;
        u8 filter[8];
 
-       pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
-
        mode = xm_read32(hw, port, XM_MODE);
        mode |= XM_MD_ENA_HASH;
        if (dev->flags & IFF_PROMISC)
@@ -2521,8 +2538,6 @@ static int skge_poll(struct net_device *dev, int *budget)
        unsigned int to_do = min(dev->quota, *budget);
        unsigned int work_done = 0;
 
-       pr_debug("skge_poll\n");
-
        for (e = ring->to_clean; work_done < to_do; e = e->next) {
                struct skge_rx_desc *rd = e->desc;
                struct sk_buff *skb;
@@ -2663,25 +2678,13 @@ static void skge_error_irq(struct skge_hw *hw)
        if (hw->chip_id == CHIP_ID_GENESIS) {
                /* clear xmac errors */
                if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
-                       skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+                       skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
                if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
-                       skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+                       skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
        } else {
                /* 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) {
@@ -2712,9 +2715,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;
                }
@@ -2876,7 +2880,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);
@@ -2895,18 +2899,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;
@@ -2914,13 +2919,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:
@@ -2948,12 +2950,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);
@@ -2994,12 +3004,8 @@ 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)
-               skge_write8(hw, GMAC_IRQ_MSK, 0);
-
        spin_lock_bh(&hw->phy_lock);
        for (i = 0; i < hw->ports; i++) {
                if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3077,6 +3083,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        /* read the mac address */
        memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        /* device is off until link detection */
        netif_carrier_off(dev);
@@ -3227,6 +3234,11 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        dev0 = hw->dev[0];
        unregister_netdev(dev0);
 
+       skge_write32(hw, B0_IMSK, 0);
+       skge_write16(hw, B0_LED, LED_STAT_OFF);
+       skge_pci_clear(hw);
+       skge_write8(hw, B0_CTST, CS_RST_SET);
+
        tasklet_kill(&hw->ext_tasklet);
 
        free_irq(pdev->irq, hw);
@@ -3235,7 +3247,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        if (dev1)
                free_netdev(dev1);
        free_netdev(dev0);
-       skge_write16(hw, B0_LED, LED_STAT_OFF);
+
        iounmap(hw->regs);
        kfree(hw);
        pci_set_drvdata(pdev, NULL);
@@ -3254,7 +3266,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
                        struct skge_port *skge = netdev_priv(dev);
                        if (netif_running(dev)) {
                                netif_carrier_off(dev);
-                               skge_down(dev);
+                               if (skge->wol)
+                                       netif_stop_queue(dev);
+                               else
+                                       skge_down(dev);
                        }
                        netif_device_detach(dev);
                        wol |= skge->wol;
This page took 0.043266 seconds and 5 git commands to generate.