Merge tag 'jg-20061012-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux...
[cascardo/linux.git] / drivers / net / tg3.c
index 2b062d7..8e39849 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.65"
-#define DRV_MODULE_RELDATE     "August 07, 2006"
+#define DRV_MODULE_VERSION     "3.67"
+#define DRV_MODULE_RELDATE     "October 18, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
 #define RX_JUMBO_PKT_BUF_SZ    (9046 + tp->rx_offset + 64)
 
 /* minimum number of free TX descriptors required to wake up TX process */
-#define TG3_TX_WAKEUP_THRESH           (TG3_TX_RING_SIZE / 4)
+#define TG3_TX_WAKEUP_THRESH(tp)               ((tp)->tx_pending / 4)
 
 /* number of ETHTOOL_GSTATS u64's */
 #define TG3_NUM_STATS          (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
@@ -1035,6 +1035,24 @@ out:
                                 phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
        }
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 phy_reg;
+
+               /* adjust output voltage */
+               tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
+
+               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
+                       u32 phy_reg2;
+
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
+                                    phy_reg | MII_TG3_EPHY_SHADOW_EN);
+                       /* Enable auto-MDIX */
+                       if (!tg3_readphy(tp, 0x10, &phy_reg2))
+                               tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
+               }
+       }
+
        tg3_phy_set_wirespeed(tp);
        return 0;
 }
@@ -1151,8 +1169,11 @@ static void tg3_power_down_phy(struct tg3 *tp)
        if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
                return;
 
-       tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF);
-       tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
+               tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                            MII_TG3_EXT_CTRL_FORCE_LED_OFF);
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+       }
 
        /* The PHY should not be powered down on some chips because
         * of bugs.
@@ -1505,6 +1526,13 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8
                break;
 
        default:
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+                       *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+                                SPEED_10;
+                       *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+                                 DUPLEX_HALF;
+                       break;
+               }
                *speed = SPEED_INVALID;
                *duplex = DUPLEX_INVALID;
                break;
@@ -1787,7 +1815,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 
        if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT)
                tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
-       else
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
                tg3_writephy(tp, MII_TG3_IMASK, ~0);
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
@@ -3047,10 +3075,10 @@ static void tg3_tx(struct tg3 *tp)
        smp_mb();
 
        if (unlikely(netif_queue_stopped(tp->dev) &&
-                    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) {
+                    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) {
                netif_tx_lock(tp->dev);
                if (netif_queue_stopped(tp->dev) &&
-                   (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))
+                   (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))
                        netif_wake_queue(tp->dev);
                netif_tx_unlock(tp->dev);
        }
@@ -3453,7 +3481,7 @@ static inline void tg3_full_unlock(struct tg3 *tp)
 /* One-shot MSI handler - Chip automatically disables interrupt
  * after sending MSI so driver doesn't have to do it.
  */
-static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct tg3 *tp = netdev_priv(dev);
@@ -3471,7 +3499,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs)
  * flush status block and interrupt mailbox. PCI ordering rules
  * guarantee that MSI will arrive after the status block.
  */
-static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_msi(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct tg3 *tp = netdev_priv(dev);
@@ -3492,7 +3520,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_RETVAL(1);
 }
 
-static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct tg3 *tp = netdev_priv(dev);
@@ -3535,7 +3563,7 @@ out:
        return IRQ_RETVAL(handled);
 }
 
-static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct tg3 *tp = netdev_priv(dev);
@@ -3578,8 +3606,7 @@ out:
 }
 
 /* ISR for interrupt test */
-static irqreturn_t tg3_test_isr(int irq, void *dev_id,
-               struct pt_regs *regs)
+static irqreturn_t tg3_test_isr(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct tg3 *tp = netdev_priv(dev);
@@ -3587,8 +3614,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
 
        if ((sblk->status & SD_STATUS_UPDATED) ||
            !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
-               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                            0x00000001);
+               tg3_disable_ints(tp);
                return IRQ_RETVAL(1);
        }
        return IRQ_RETVAL(0);
@@ -3624,7 +3650,7 @@ static void tg3_poll_controller(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       tg3_interrupt(tp->pdev->irq, dev, NULL);
+       tg3_interrupt(tp->pdev->irq, dev);
 }
 #endif
 
@@ -3902,7 +3928,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tp->tx_prod = entry;
        if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
                netif_stop_queue(dev);
-               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
+               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
                        netif_wake_queue(tp->dev);
        }
 
@@ -4117,7 +4143,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        tp->tx_prod = entry;
        if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
                netif_stop_queue(dev);
-               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
+               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
                        netif_wake_queue(tp->dev);
        }
 
@@ -6552,7 +6578,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        if (err)
                return err;
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
                u32 tmp;
 
                /* Clear CRC stats. */
@@ -6810,7 +6837,7 @@ restart_timer:
 
 static int tg3_request_irq(struct tg3 *tp)
 {
-       irqreturn_t (*fn)(int, void *, struct pt_regs *);
+       irq_handler_t fn;
        unsigned long flags;
        struct net_device *dev = tp->dev;
 
@@ -6831,8 +6858,7 @@ static int tg3_request_irq(struct tg3 *tp)
 static int tg3_test_interrupt(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
-       int err, i;
-       u32 int_mbox = 0;
+       int err, i, intr_ok = 0;
 
        if (!netif_running(dev))
                return -ENODEV;
@@ -6853,10 +6879,18 @@ static int tg3_test_interrupt(struct tg3 *tp)
               HOSTCC_MODE_NOW);
 
        for (i = 0; i < 5; i++) {
+               u32 int_mbox, misc_host_ctrl;
+
                int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 +
                                        TG3_64BIT_REG_LOW);
-               if (int_mbox != 0)
+               misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
+
+               if ((int_mbox != 0) ||
+                   (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) {
+                       intr_ok = 1;
                        break;
+               }
+
                msleep(10);
        }
 
@@ -6869,7 +6903,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
        if (err)
                return err;
 
-       if (int_mbox != 0)
+       if (intr_ok)
                return 0;
 
        return -EIO;
@@ -8072,7 +8106,10 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 
        if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
            (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
-           (ering->tx_pending > TG3_TX_RING_SIZE - 1))
+           (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
+           (ering->tx_pending <= MAX_SKB_FRAGS) ||
+           ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) &&
+            (ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
                return -EINVAL;
 
        if (netif_running(dev)) {
@@ -8259,6 +8296,8 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
 
 #define NVRAM_TEST_SIZE 0x100
 #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_HW_SIZE 0x20
+#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
@@ -8270,12 +8309,14 @@ static int tg3_test_nvram(struct tg3 *tp)
 
        if (magic == TG3_EEPROM_MAGIC)
                size = NVRAM_TEST_SIZE;
-       else if ((magic & 0xff000000) == 0xa5000000) {
+       else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
                if ((magic & 0xe00000) == 0x200000)
                        size = NVRAM_SELFBOOT_FORMAT1_SIZE;
                else
                        return 0;
-       } else
+       } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
+               size = NVRAM_SELFBOOT_HW_SIZE;
+       else
                return -EIO;
 
        buf = kmalloc(size, GFP_KERNEL);
@@ -8294,7 +8335,8 @@ static int tg3_test_nvram(struct tg3 *tp)
                goto out;
 
        /* Selfboot format */
-       if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) {
+       if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) ==
+           TG3_EEPROM_MAGIC_FW) {
                u8 *buf8 = (u8 *) buf, csum8 = 0;
 
                for (i = 0; i < size; i++)
@@ -8309,6 +8351,51 @@ static int tg3_test_nvram(struct tg3 *tp)
                goto out;
        }
 
+       if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) ==
+           TG3_EEPROM_MAGIC_HW) {
+               u8 data[NVRAM_SELFBOOT_DATA_SIZE];
+               u8 parity[NVRAM_SELFBOOT_DATA_SIZE];
+               u8 *buf8 = (u8 *) buf;
+               int j, k;
+
+               /* Separate the parity bits and the data bytes.  */
+               for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) {
+                       if ((i == 0) || (i == 8)) {
+                               int l;
+                               u8 msk;
+
+                               for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1)
+                                       parity[k++] = buf8[i] & msk;
+                               i++;
+                       }
+                       else if (i == 16) {
+                               int l;
+                               u8 msk;
+
+                               for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1)
+                                       parity[k++] = buf8[i] & msk;
+                               i++;
+
+                               for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1)
+                                       parity[k++] = buf8[i] & msk;
+                               i++;
+                       }
+                       data[j++] = buf8[i];
+               }
+
+               err = -EIO;
+               for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) {
+                       u8 hw8 = hweight8(data[i]);
+
+                       if ((hw8 & 0x1) && parity[i])
+                               goto out;
+                       else if (!(hw8 & 0x1) && !parity[i])
+                               goto out;
+               }
+               err = 0;
+               goto out;
+       }
+
        /* Bootstrap checksum at offset 0x10 */
        csum = calc_crc((unsigned char *) buf, 0x10);
        if(csum != cpu_to_le32(buf[0x10/4]))
@@ -8355,7 +8442,7 @@ static int tg3_test_link(struct tg3 *tp)
 /* Only test the commonly used registers */
 static int tg3_test_registers(struct tg3 *tp)
 {
-       int i, is_5705;
+       int i, is_5705, is_5750;
        u32 offset, read_mask, write_mask, val, save_val, read_val;
        static struct {
                u16 offset;
@@ -8363,6 +8450,7 @@ static int tg3_test_registers(struct tg3 *tp)
 #define TG3_FL_5705    0x1
 #define TG3_FL_NOT_5705        0x2
 #define TG3_FL_NOT_5788        0x4
+#define TG3_FL_NOT_5750        0x8
                u32 read_mask;
                u32 write_mask;
        } reg_tbl[] = {
@@ -8473,9 +8561,9 @@ static int tg3_test_registers(struct tg3 *tp)
                        0xffffffff, 0x00000000 },
 
                /* Buffer Manager Control Registers. */
-               { BUFMGR_MB_POOL_ADDR, 0x0000,
+               { BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750,
                        0x00000000, 0x007fff80 },
-               { BUFMGR_MB_POOL_SIZE, 0x0000,
+               { BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750,
                        0x00000000, 0x007fffff },
                { BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
                        0x00000000, 0x0000003f },
@@ -8501,10 +8589,12 @@ static int tg3_test_registers(struct tg3 *tp)
                { 0xffff, 0x0000, 0x00000000, 0x00000000 },
        };
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+       is_5705 = is_5750 = 0;
+       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
                is_5705 = 1;
-       else
-               is_5705 = 0;
+               if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
+                       is_5750 = 1;
+       }
 
        for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
                if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
@@ -8517,6 +8607,9 @@ static int tg3_test_registers(struct tg3 *tp)
                    (reg_tbl[i].flags & TG3_FL_NOT_5788))
                        continue;
 
+               if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750))
+                       continue;
+
                offset = (u32) reg_tbl[i].offset;
                read_mask = reg_tbl[i].read_mask;
                write_mask = reg_tbl[i].write_mask;
@@ -8608,6 +8701,13 @@ static int tg3_test_memory(struct tg3 *tp)
                { 0x00008000, 0x02000},
                { 0x00010000, 0x0c000},
                { 0xffffffff, 0x00000}
+       }, mem_tbl_5906[] = {
+               { 0x00000200, 0x00008},
+               { 0x00004000, 0x00400},
+               { 0x00006000, 0x00400},
+               { 0x00008000, 0x01000},
+               { 0x00010000, 0x01000},
+               { 0xffffffff, 0x00000}
        };
        struct mem_entry *mem_tbl;
        int err = 0;
@@ -8617,6 +8717,8 @@ static int tg3_test_memory(struct tg3 *tp)
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
                        mem_tbl = mem_tbl_5755;
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+                       mem_tbl = mem_tbl_5906;
                else
                        mem_tbl = mem_tbl_5705;
        } else
@@ -8662,6 +8764,21 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        } else if (loopback_mode == TG3_PHY_LOOPBACK) {
                u32 val;
 
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+                       u32 phytest;
+
+                       if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) {
+                               u32 phy;
+
+                               tg3_writephy(tp, MII_TG3_EPHY_TEST,
+                                            phytest | MII_TG3_EPHY_SHADOW_EN);
+                               if (!tg3_readphy(tp, 0x1b, &phy))
+                                       tg3_writephy(tp, 0x1b, phy & ~0x20);
+                               if (!tg3_readphy(tp, 0x10, &phy))
+                                       tg3_writephy(tp, 0x10, phy & ~0x4000);
+                               tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
+                       }
+               }
                val = BMCR_LOOPBACK | BMCR_FULLDPLX;
                if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
                        val |= BMCR_SPEED100;
@@ -8670,6 +8787,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
                tg3_writephy(tp, MII_BMCR, val);
                udelay(40);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+                       tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
+
                /* reset to prevent losing 1st rx packet intermittently */
                if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
                        tw32_f(MAC_RX_MODE, RX_MODE_RESET);
@@ -9083,7 +9203,9 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
        if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
                return;
 
-       if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000))
+       if ((magic != TG3_EEPROM_MAGIC) &&
+           ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) &&
+           ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW))
                return;
 
        /*