]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/broadcom/tg3.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / drivers / net / ethernet / broadcom / tg3.c
index a1f2e0fed78bc2b23b7caa2c1457255e6eae9b89..b0657466041d733900199124ffab0f6dbaf088af 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2005-2011 Broadcom Corporation.
+ * Copyright (C) 2005-2012 Broadcom Corporation.
  *
  * Firmware is:
  *     Derived from proprietary unpublished source code,
@@ -204,6 +204,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 #define TG3_RAW_IP_ALIGN 2
 
 #define TG3_FW_UPDATE_TIMEOUT_SEC      5
+#define TG3_FW_UPDATE_FREQ_SEC         (TG3_FW_UPDATE_TIMEOUT_SEC / 2)
 
 #define FIRMWARE_TG3           "tigon/tg3.bin"
 #define FIRMWARE_TG3TSO                "tigon/tg3_tso.bin"
@@ -1453,33 +1454,23 @@ static void tg3_wait_for_event_ack(struct tg3 *tp)
 }
 
 /* tp->lock is held. */
-static void tg3_ump_link_report(struct tg3 *tp)
+static void tg3_phy_gather_ump_data(struct tg3 *tp, u32 *data)
 {
-       u32 reg;
-       u32 val;
-
-       if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
-               return;
-
-       tg3_wait_for_event_ack(tp);
-
-       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
-
-       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+       u32 reg, val;
 
        val = 0;
        if (!tg3_readphy(tp, MII_BMCR, &reg))
                val = reg << 16;
        if (!tg3_readphy(tp, MII_BMSR, &reg))
                val |= (reg & 0xffff);
-       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+       *data++ = val;
 
        val = 0;
        if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
                val = reg << 16;
        if (!tg3_readphy(tp, MII_LPA, &reg))
                val |= (reg & 0xffff);
-       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+       *data++ = val;
 
        val = 0;
        if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
@@ -1488,13 +1479,33 @@ static void tg3_ump_link_report(struct tg3 *tp)
                if (!tg3_readphy(tp, MII_STAT1000, &reg))
                        val |= (reg & 0xffff);
        }
-       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+       *data++ = val;
 
        if (!tg3_readphy(tp, MII_PHYADDR, &reg))
                val = reg << 16;
        else
                val = 0;
-       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+       *data++ = val;
+}
+
+/* tp->lock is held. */
+static void tg3_ump_link_report(struct tg3 *tp)
+{
+       u32 data[4];
+
+       if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
+               return;
+
+       tg3_phy_gather_ump_data(tp, data);
+
+       tg3_wait_for_event_ack(tp);
+
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x0, data[0]);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x4, data[1]);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x8, data[2]);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0xc, data[3]);
 
        tg3_generate_fw_event(tp);
 }
@@ -1809,13 +1820,13 @@ static void tg3_adjust_link(struct net_device *dev)
                      (6 << TX_LENGTHS_IPG_SHIFT) |
                      (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
 
-       if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) ||
-           (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) ||
+       if (phydev->link != tp->old_link ||
            phydev->speed != tp->link_config.active_speed ||
            phydev->duplex != tp->link_config.active_duplex ||
            oldflowctrl != tp->link_config.active_flowctrl)
                linkmesg = 1;
 
+       tp->old_link = phydev->link;
        tp->link_config.active_speed = phydev->speed;
        tp->link_config.active_duplex = phydev->duplex;
 
@@ -1884,10 +1895,10 @@ static void tg3_phy_start(struct tg3 *tp)
 
        if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
                tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
-               phydev->speed = tp->link_config.orig_speed;
-               phydev->duplex = tp->link_config.orig_duplex;
-               phydev->autoneg = tp->link_config.orig_autoneg;
-               phydev->advertising = tp->link_config.orig_advertising;
+               phydev->speed = tp->link_config.speed;
+               phydev->duplex = tp->link_config.duplex;
+               phydev->autoneg = tp->link_config.autoneg;
+               phydev->advertising = tp->link_config.advertising;
        }
 
        phy_start(phydev);
@@ -2709,9 +2720,6 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
        return 0;
 }
 
-static int tg3_setup_phy(struct tg3 *, int);
-static int tg3_halt_cpu(struct tg3 *, u32);
-
 static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
        u32 val;
@@ -2978,1266 +2986,1501 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val)
        return res;
 }
 
-#define RX_CPU_SCRATCH_BASE    0x30000
-#define RX_CPU_SCRATCH_SIZE    0x04000
-#define TX_CPU_SCRATCH_BASE    0x34000
-#define TX_CPU_SCRATCH_SIZE    0x04000
-
-/* tp->lock is held. */
-static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
+static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
+                                   u32 offset, u32 len, u8 *buf)
 {
-       int i;
+       int i, j, rc = 0;
+       u32 val;
 
-       BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
+       for (i = 0; i < len; i += 4) {
+               u32 addr;
+               __be32 data;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 val = tr32(GRC_VCPU_EXT_CTRL);
+               addr = offset + i;
 
-               tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
-               return 0;
-       }
-       if (offset == RX_CPU_BASE) {
-               for (i = 0; i < 10000; i++) {
-                       tw32(offset + CPU_STATE, 0xffffffff);
-                       tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-                       if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
-                               break;
-               }
+               memcpy(&data, buf + i, 4);
 
-               tw32(offset + CPU_STATE, 0xffffffff);
-               tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
-               udelay(10);
-       } else {
-               for (i = 0; i < 10000; i++) {
-                       tw32(offset + CPU_STATE, 0xffffffff);
-                       tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-                       if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
+               /*
+                * The SEEPROM interface expects the data to always be opposite
+                * the native endian format.  We accomplish this by reversing
+                * all the operations that would have been performed on the
+                * data from a call to tg3_nvram_read_be32().
+                */
+               tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data)));
+
+               val = tr32(GRC_EEPROM_ADDR);
+               tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
+
+               val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK |
+                       EEPROM_ADDR_READ);
+               tw32(GRC_EEPROM_ADDR, val |
+                       (0 << EEPROM_ADDR_DEVID_SHIFT) |
+                       (addr & EEPROM_ADDR_ADDR_MASK) |
+                       EEPROM_ADDR_START |
+                       EEPROM_ADDR_WRITE);
+
+               for (j = 0; j < 1000; j++) {
+                       val = tr32(GRC_EEPROM_ADDR);
+
+                       if (val & EEPROM_ADDR_COMPLETE)
                                break;
+                       msleep(1);
+               }
+               if (!(val & EEPROM_ADDR_COMPLETE)) {
+                       rc = -EBUSY;
+                       break;
                }
        }
 
-       if (i >= 10000) {
-               netdev_err(tp->dev, "%s timed out, %s CPU\n",
-                          __func__, offset == RX_CPU_BASE ? "RX" : "TX");
-               return -ENODEV;
-       }
-
-       /* Clear firmware's nvram arbitration. */
-       if (tg3_flag(tp, NVRAM))
-               tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
-       return 0;
+       return rc;
 }
 
-struct fw_info {
-       unsigned int fw_base;
-       unsigned int fw_len;
-       const __be32 *fw_data;
-};
-
-/* tp->lock is held. */
-static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
-                                u32 cpu_scratch_base, int cpu_scratch_size,
-                                struct fw_info *info)
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
+               u8 *buf)
 {
-       int err, lock_err, i;
-       void (*write_op)(struct tg3 *, u32, u32);
+       int ret = 0;
+       u32 pagesize = tp->nvram_pagesize;
+       u32 pagemask = pagesize - 1;
+       u32 nvram_cmd;
+       u8 *tmp;
 
-       if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) {
-               netdev_err(tp->dev,
-                          "%s: Trying to load TX cpu firmware which is 5705\n",
-                          __func__);
-               return -EINVAL;
-       }
+       tmp = kmalloc(pagesize, GFP_KERNEL);
+       if (tmp == NULL)
+               return -ENOMEM;
 
-       if (tg3_flag(tp, 5705_PLUS))
-               write_op = tg3_write_mem;
-       else
-               write_op = tg3_write_indirect_reg32;
+       while (len) {
+               int j;
+               u32 phy_addr, page_off, size;
 
-       /* It is possible that bootcode is still loading at this point.
-        * Get the nvram lock first before halting the cpu.
-        */
-       lock_err = tg3_nvram_lock(tp);
-       err = tg3_halt_cpu(tp, cpu_base);
-       if (!lock_err)
-               tg3_nvram_unlock(tp);
-       if (err)
-               goto out;
+               phy_addr = offset & ~pagemask;
 
-       for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
-               write_op(tp, cpu_scratch_base + i, 0);
-       tw32(cpu_base + CPU_STATE, 0xffffffff);
-       tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
-       for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
-               write_op(tp, (cpu_scratch_base +
-                             (info->fw_base & 0xffff) +
-                             (i * sizeof(u32))),
-                             be32_to_cpu(info->fw_data[i]));
+               for (j = 0; j < pagesize; j += 4) {
+                       ret = tg3_nvram_read_be32(tp, phy_addr + j,
+                                                 (__be32 *) (tmp + j));
+                       if (ret)
+                               break;
+               }
+               if (ret)
+                       break;
 
-       err = 0;
+               page_off = offset & pagemask;
+               size = pagesize;
+               if (len < size)
+                       size = len;
 
-out:
-       return err;
-}
+               len -= size;
 
-/* tp->lock is held. */
-static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
-{
-       struct fw_info info;
-       const __be32 *fw_data;
-       int err, i;
+               memcpy(tmp + page_off, buf, size);
 
-       fw_data = (void *)tp->fw->data;
+               offset = offset + (pagesize - page_off);
 
-       /* Firmware blob starts with version numbers, followed by
-          start address and length. We are setting complete length.
-          length = end_address_of_bss - start_address_of_text.
-          Remainder is the blob to be loaded contiguously
-          from start address. */
+               tg3_enable_nvram_access(tp);
 
-       info.fw_base = be32_to_cpu(fw_data[1]);
-       info.fw_len = tp->fw->size - 12;
-       info.fw_data = &fw_data[3];
+               /*
+                * Before we can erase the flash page, we need
+                * to issue a special "write enable" command.
+                */
+               nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
 
-       err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
-                                   RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
-                                   &info);
-       if (err)
-               return err;
+               if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+                       break;
 
-       err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
-                                   TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
-                                   &info);
-       if (err)
-               return err;
+               /* Erase the target page */
+               tw32(NVRAM_ADDR, phy_addr);
 
-       /* Now startup only the RX cpu. */
-       tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-       tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
+               nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR |
+                       NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE;
 
-       for (i = 0; i < 5; i++) {
-               if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
+               if (tg3_nvram_exec_cmd(tp, nvram_cmd))
                        break;
-               tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-               tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-               tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
-               udelay(1000);
-       }
-       if (i >= 5) {
-               netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
-                          "should be %08x\n", __func__,
-                          tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
-               return -ENODEV;
-       }
-       tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-       tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 
-       return 0;
-}
+               /* Issue another write enable to start the write. */
+               nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
 
-/* tp->lock is held. */
-static int tg3_load_tso_firmware(struct tg3 *tp)
-{
-       struct fw_info info;
-       const __be32 *fw_data;
-       unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
-       int err, i;
+               if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+                       break;
 
-       if (tg3_flag(tp, HW_TSO_1) ||
-           tg3_flag(tp, HW_TSO_2) ||
-           tg3_flag(tp, HW_TSO_3))
-               return 0;
+               for (j = 0; j < pagesize; j += 4) {
+                       __be32 data;
 
-       fw_data = (void *)tp->fw->data;
+                       data = *((__be32 *) (tmp + j));
 
-       /* Firmware blob starts with version numbers, followed by
-          start address and length. We are setting complete length.
-          length = end_address_of_bss - start_address_of_text.
-          Remainder is the blob to be loaded contiguously
-          from start address. */
-
-       info.fw_base = be32_to_cpu(fw_data[1]);
-       cpu_scratch_size = tp->fw_len;
-       info.fw_len = tp->fw->size - 12;
-       info.fw_data = &fw_data[3];
+                       tw32(NVRAM_WRDATA, be32_to_cpu(data));
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-               cpu_base = RX_CPU_BASE;
-               cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
-       } else {
-               cpu_base = TX_CPU_BASE;
-               cpu_scratch_base = TX_CPU_SCRATCH_BASE;
-               cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
-       }
+                       tw32(NVRAM_ADDR, phy_addr + j);
 
-       err = tg3_load_firmware_cpu(tp, cpu_base,
-                                   cpu_scratch_base, cpu_scratch_size,
-                                   &info);
-       if (err)
-               return err;
+                       nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE |
+                               NVRAM_CMD_WR;
 
-       /* Now startup the cpu. */
-       tw32(cpu_base + CPU_STATE, 0xffffffff);
-       tw32_f(cpu_base + CPU_PC, info.fw_base);
+                       if (j == 0)
+                               nvram_cmd |= NVRAM_CMD_FIRST;
+                       else if (j == (pagesize - 4))
+                               nvram_cmd |= NVRAM_CMD_LAST;
 
-       for (i = 0; i < 5; i++) {
-               if (tr32(cpu_base + CPU_PC) == info.fw_base)
+                       ret = tg3_nvram_exec_cmd(tp, nvram_cmd);
+                       if (ret)
+                               break;
+               }
+               if (ret)
                        break;
-               tw32(cpu_base + CPU_STATE, 0xffffffff);
-               tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-               tw32_f(cpu_base + CPU_PC, info.fw_base);
-               udelay(1000);
-       }
-       if (i >= 5) {
-               netdev_err(tp->dev,
-                          "%s fails to set CPU PC, is %08x should be %08x\n",
-                          __func__, tr32(cpu_base + CPU_PC), info.fw_base);
-               return -ENODEV;
-       }
-       tw32(cpu_base + CPU_STATE, 0xffffffff);
-       tw32_f(cpu_base + CPU_MODE,  0x00000000);
-       return 0;
-}
-
-
-/* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
-{
-       u32 addr_high, addr_low;
-       int i;
-
-       addr_high = ((tp->dev->dev_addr[0] << 8) |
-                    tp->dev->dev_addr[1]);
-       addr_low = ((tp->dev->dev_addr[2] << 24) |
-                   (tp->dev->dev_addr[3] << 16) |
-                   (tp->dev->dev_addr[4] <<  8) |
-                   (tp->dev->dev_addr[5] <<  0));
-       for (i = 0; i < 4; i++) {
-               if (i == 1 && skip_mac_1)
-                       continue;
-               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
-               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-               for (i = 0; i < 12; i++) {
-                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
-                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
-               }
-       }
+       nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+       tg3_nvram_exec_cmd(tp, nvram_cmd);
 
-       addr_high = (tp->dev->dev_addr[0] +
-                    tp->dev->dev_addr[1] +
-                    tp->dev->dev_addr[2] +
-                    tp->dev->dev_addr[3] +
-                    tp->dev->dev_addr[4] +
-                    tp->dev->dev_addr[5]) &
-               TX_BACKOFF_SEED_MASK;
-       tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
+       kfree(tmp);
 
-static void tg3_enable_register_access(struct tg3 *tp)
-{
-       /*
-        * Make sure register accesses (indirect or otherwise) will function
-        * correctly.
-        */
-       pci_write_config_dword(tp->pdev,
-                              TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+       return ret;
 }
 
-static int tg3_power_up(struct tg3 *tp)
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
+               u8 *buf)
 {
-       int err;
+       int i, ret = 0;
 
-       tg3_enable_register_access(tp);
+       for (i = 0; i < len; i += 4, offset += 4) {
+               u32 page_off, phy_addr, nvram_cmd;
+               __be32 data;
 
-       err = pci_set_power_state(tp->pdev, PCI_D0);
-       if (!err) {
-               /* Switch out of Vaux if it is a NIC */
-               tg3_pwrsrc_switch_to_vmain(tp);
-       } else {
-               netdev_err(tp->dev, "Transition to D0 failed\n");
-       }
+               memcpy(&data, buf + i, 4);
+               tw32(NVRAM_WRDATA, be32_to_cpu(data));
 
-       return err;
-}
+               page_off = offset % tp->nvram_pagesize;
 
-static int tg3_power_down_prepare(struct tg3 *tp)
-{
-       u32 misc_host_ctrl;
-       bool device_should_wake, do_low_power;
+               phy_addr = tg3_nvram_phys_addr(tp, offset);
 
-       tg3_enable_register_access(tp);
+               nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR;
 
-       /* Restore the CLKREQ setting. */
-       if (tg3_flag(tp, CLKREQ_BUG)) {
-               u16 lnkctl;
+               if (page_off == 0 || i == 0)
+                       nvram_cmd |= NVRAM_CMD_FIRST;
+               if (page_off == (tp->nvram_pagesize - 4))
+                       nvram_cmd |= NVRAM_CMD_LAST;
 
-               pci_read_config_word(tp->pdev,
-                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                    &lnkctl);
-               lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
-               pci_write_config_word(tp->pdev,
-                                     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                     lnkctl);
-       }
+               if (i == (len - 4))
+                       nvram_cmd |= NVRAM_CMD_LAST;
 
-       misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
-       tw32(TG3PCI_MISC_HOST_CTRL,
-            misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
+               if ((nvram_cmd & NVRAM_CMD_FIRST) ||
+                   !tg3_flag(tp, FLASH) ||
+                   !tg3_flag(tp, 57765_PLUS))
+                       tw32(NVRAM_ADDR, phy_addr);
 
-       device_should_wake = device_may_wakeup(&tp->pdev->dev) &&
-                            tg3_flag(tp, WOL_ENABLE);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
+                   !tg3_flag(tp, 5755_PLUS) &&
+                   (tp->nvram_jedecnum == JEDEC_ST) &&
+                   (nvram_cmd & NVRAM_CMD_FIRST)) {
+                       u32 cmd;
 
-       if (tg3_flag(tp, USE_PHYLIB)) {
-               do_low_power = false;
-               if ((tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) &&
-                   !(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
-                       struct phy_device *phydev;
-                       u32 phyid, advertising;
+                       cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+                       ret = tg3_nvram_exec_cmd(tp, cmd);
+                       if (ret)
+                               break;
+               }
+               if (!tg3_flag(tp, FLASH)) {
+                       /* We always do complete word writes to eeprom. */
+                       nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST);
+               }
 
-                       phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
+               ret = tg3_nvram_exec_cmd(tp, nvram_cmd);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
 
-                       tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
+{
+       int ret;
 
-                       tp->link_config.orig_speed = phydev->speed;
-                       tp->link_config.orig_duplex = phydev->duplex;
-                       tp->link_config.orig_autoneg = phydev->autoneg;
-                       tp->link_config.orig_advertising = phydev->advertising;
+       if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
+               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
+                      ~GRC_LCLCTRL_GPIO_OUTPUT1);
+               udelay(40);
+       }
 
-                       advertising = ADVERTISED_TP |
-                                     ADVERTISED_Pause |
-                                     ADVERTISED_Autoneg |
-                                     ADVERTISED_10baseT_Half;
+       if (!tg3_flag(tp, NVRAM)) {
+               ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf);
+       } else {
+               u32 grc_mode;
 
-                       if (tg3_flag(tp, ENABLE_ASF) || device_should_wake) {
-                               if (tg3_flag(tp, WOL_SPEED_100MB))
-                                       advertising |=
-                                               ADVERTISED_100baseT_Half |
-                                               ADVERTISED_100baseT_Full |
-                                               ADVERTISED_10baseT_Full;
-                               else
-                                       advertising |= ADVERTISED_10baseT_Full;
-                       }
+               ret = tg3_nvram_lock(tp);
+               if (ret)
+                       return ret;
 
-                       phydev->advertising = advertising;
+               tg3_enable_nvram_access(tp);
+               if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM))
+                       tw32(NVRAM_WRITE1, 0x406);
 
-                       phy_start_aneg(phydev);
+               grc_mode = tr32(GRC_MODE);
+               tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE);
 
-                       phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
-                       if (phyid != PHY_ID_BCMAC131) {
-                               phyid &= PHY_BCM_OUI_MASK;
-                               if (phyid == PHY_BCM_OUI_1 ||
-                                   phyid == PHY_BCM_OUI_2 ||
-                                   phyid == PHY_BCM_OUI_3)
-                                       do_low_power = true;
-                       }
+               if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) {
+                       ret = tg3_nvram_write_block_buffered(tp, offset, len,
+                               buf);
+               } else {
+                       ret = tg3_nvram_write_block_unbuffered(tp, offset, len,
+                               buf);
                }
-       } else {
-               do_low_power = true;
 
-               if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
-                       tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
-                       tp->link_config.orig_speed = tp->link_config.speed;
-                       tp->link_config.orig_duplex = tp->link_config.duplex;
-                       tp->link_config.orig_autoneg = tp->link_config.autoneg;
-               }
+               grc_mode = tr32(GRC_MODE);
+               tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE);
 
-               if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) {
-                       tp->link_config.speed = SPEED_10;
-                       tp->link_config.duplex = DUPLEX_HALF;
-                       tp->link_config.autoneg = AUTONEG_ENABLE;
-                       tg3_setup_phy(tp, 0);
-               }
+               tg3_disable_nvram_access(tp);
+               tg3_nvram_unlock(tp);
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 val;
+       if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
+               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+               udelay(40);
+       }
 
-               val = tr32(GRC_VCPU_EXT_CTRL);
-               tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL);
-       } else if (!tg3_flag(tp, ENABLE_ASF)) {
-               int i;
-               u32 val;
+       return ret;
+}
 
-               for (i = 0; i < 200; i++) {
-                       tg3_read_mem(tp, NIC_SRAM_FW_ASF_STATUS_MBOX, &val);
-                       if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-                               break;
-                       msleep(1);
-               }
-       }
-       if (tg3_flag(tp, WOL_CAP))
-               tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
-                                                    WOL_DRV_STATE_SHUTDOWN |
-                                                    WOL_DRV_WOL |
-                                                    WOL_SET_MAGIC_PKT);
+#define RX_CPU_SCRATCH_BASE    0x30000
+#define RX_CPU_SCRATCH_SIZE    0x04000
+#define TX_CPU_SCRATCH_BASE    0x34000
+#define TX_CPU_SCRATCH_SIZE    0x04000
 
-       if (device_should_wake) {
-               u32 mac_mode;
+/* tp->lock is held. */
+static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
+{
+       int i;
 
-               if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
-                       if (do_low_power &&
-                           !(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
-                               tg3_phy_auxctl_write(tp,
-                                              MII_TG3_AUXCTL_SHDWSEL_PWRCTL,
-                                              MII_TG3_AUXCTL_PCTL_WOL_EN |
-                                              MII_TG3_AUXCTL_PCTL_100TX_LPWR |
-                                              MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC);
-                               udelay(40);
-                       }
+       BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
 
-                       if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
-                               mac_mode = MAC_MODE_PORT_MODE_GMII;
-                       else
-                               mac_mode = MAC_MODE_PORT_MODE_MII;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 val = tr32(GRC_VCPU_EXT_CTRL);
 
-                       mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
-                           ASIC_REV_5700) {
-                               u32 speed = tg3_flag(tp, WOL_SPEED_100MB) ?
-                                            SPEED_100 : SPEED_10;
-                               if (tg3_5700_link_polarity(tp, speed))
-                                       mac_mode |= MAC_MODE_LINK_POLARITY;
-                               else
-                                       mac_mode &= ~MAC_MODE_LINK_POLARITY;
-                       }
-               } else {
-                       mac_mode = MAC_MODE_PORT_MODE_TBI;
+               tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
+               return 0;
+       }
+       if (offset == RX_CPU_BASE) {
+               for (i = 0; i < 10000; i++) {
+                       tw32(offset + CPU_STATE, 0xffffffff);
+                       tw32(offset + CPU_MODE,  CPU_MODE_HALT);
+                       if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
+                               break;
                }
 
-               if (!tg3_flag(tp, 5750_PLUS))
-                       tw32(MAC_LED_CTRL, tp->led_ctrl);
+               tw32(offset + CPU_STATE, 0xffffffff);
+               tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
+               udelay(10);
+       } else {
+               for (i = 0; i < 10000; i++) {
+                       tw32(offset + CPU_STATE, 0xffffffff);
+                       tw32(offset + CPU_MODE,  CPU_MODE_HALT);
+                       if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
+                               break;
+               }
+       }
 
-               mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
-               if ((tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS)) &&
-                   (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)))
-                       mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
+       if (i >= 10000) {
+               netdev_err(tp->dev, "%s timed out, %s CPU\n",
+                          __func__, offset == RX_CPU_BASE ? "RX" : "TX");
+               return -ENODEV;
+       }
 
-               if (tg3_flag(tp, ENABLE_APE))
-                       mac_mode |= MAC_MODE_APE_TX_EN |
-                                   MAC_MODE_APE_RX_EN |
-                                   MAC_MODE_TDE_ENABLE;
+       /* Clear firmware's nvram arbitration. */
+       if (tg3_flag(tp, NVRAM))
+               tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
+       return 0;
+}
 
-               tw32_f(MAC_MODE, mac_mode);
-               udelay(100);
+struct fw_info {
+       unsigned int fw_base;
+       unsigned int fw_len;
+       const __be32 *fw_data;
+};
 
-               tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
-               udelay(10);
-       }
+/* tp->lock is held. */
+static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
+                                u32 cpu_scratch_base, int cpu_scratch_size,
+                                struct fw_info *info)
+{
+       int err, lock_err, i;
+       void (*write_op)(struct tg3 *, u32, u32);
 
-       if (!tg3_flag(tp, WOL_SPEED_100MB) &&
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
-               u32 base_val;
+       if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) {
+               netdev_err(tp->dev,
+                          "%s: Trying to load TX cpu firmware which is 5705\n",
+                          __func__);
+               return -EINVAL;
+       }
 
-               base_val = tp->pci_clock_ctrl;
-               base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
-                            CLOCK_CTRL_TXCLK_DISABLE);
+       if (tg3_flag(tp, 5705_PLUS))
+               write_op = tg3_write_mem;
+       else
+               write_op = tg3_write_indirect_reg32;
 
-               tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
-                           CLOCK_CTRL_PWRDOWN_PLL133, 40);
-       } else if (tg3_flag(tp, 5780_CLASS) ||
-                  tg3_flag(tp, CPMU_PRESENT) ||
-                  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               /* do nothing */
-       } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) {
-               u32 newbits1, newbits2;
+       /* It is possible that bootcode is still loading at this point.
+        * Get the nvram lock first before halting the cpu.
+        */
+       lock_err = tg3_nvram_lock(tp);
+       err = tg3_halt_cpu(tp, cpu_base);
+       if (!lock_err)
+               tg3_nvram_unlock(tp);
+       if (err)
+               goto out;
 
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-                       newbits1 = (CLOCK_CTRL_RXCLK_DISABLE |
-                                   CLOCK_CTRL_TXCLK_DISABLE |
-                                   CLOCK_CTRL_ALTCLK);
-                       newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
-               } else if (tg3_flag(tp, 5705_PLUS)) {
-                       newbits1 = CLOCK_CTRL_625_CORE;
-                       newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
-               } else {
-                       newbits1 = CLOCK_CTRL_ALTCLK;
-                       newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
-               }
+       for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
+               write_op(tp, cpu_scratch_base + i, 0);
+       tw32(cpu_base + CPU_STATE, 0xffffffff);
+       tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
+       for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
+               write_op(tp, (cpu_scratch_base +
+                             (info->fw_base & 0xffff) +
+                             (i * sizeof(u32))),
+                             be32_to_cpu(info->fw_data[i]));
 
-               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1,
-                           40);
+       err = 0;
 
-               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2,
-                           40);
+out:
+       return err;
+}
 
-               if (!tg3_flag(tp, 5705_PLUS)) {
-                       u32 newbits3;
+/* tp->lock is held. */
+static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
+{
+       struct fw_info info;
+       const __be32 *fw_data;
+       int err, i;
 
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-                               newbits3 = (CLOCK_CTRL_RXCLK_DISABLE |
-                                           CLOCK_CTRL_TXCLK_DISABLE |
-                                           CLOCK_CTRL_44MHZ_CORE);
-                       } else {
-                               newbits3 = CLOCK_CTRL_44MHZ_CORE;
-                       }
+       fw_data = (void *)tp->fw->data;
 
-                       tw32_wait_f(TG3PCI_CLOCK_CTRL,
-                                   tp->pci_clock_ctrl | newbits3, 40);
-               }
-       }
+       /* Firmware blob starts with version numbers, followed by
+          start address and length. We are setting complete length.
+          length = end_address_of_bss - start_address_of_text.
+          Remainder is the blob to be loaded contiguously
+          from start address. */
 
-       if (!(device_should_wake) && !tg3_flag(tp, ENABLE_ASF))
-               tg3_power_down_phy(tp, do_low_power);
+       info.fw_base = be32_to_cpu(fw_data[1]);
+       info.fw_len = tp->fw->size - 12;
+       info.fw_data = &fw_data[3];
 
-       tg3_frob_aux_power(tp, true);
+       err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
+                                   RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
+                                   &info);
+       if (err)
+               return err;
 
-       /* Workaround for unstable PLL clock */
-       if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
-           (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
-               u32 val = tr32(0x7d00);
+       err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
+                                   TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
+                                   &info);
+       if (err)
+               return err;
 
-               val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
-               tw32(0x7d00, val);
-               if (!tg3_flag(tp, ENABLE_ASF)) {
-                       int err;
+       /* Now startup only the RX cpu. */
+       tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+       tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
 
-                       err = tg3_nvram_lock(tp);
-                       tg3_halt_cpu(tp, RX_CPU_BASE);
-                       if (!err)
-                               tg3_nvram_unlock(tp);
-               }
+       for (i = 0; i < 5; i++) {
+               if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
+                       break;
+               tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+               tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
+               tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
+               udelay(1000);
        }
-
-       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+       if (i >= 5) {
+               netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
+                          "should be %08x\n", __func__,
+                          tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
+               return -ENODEV;
+       }
+       tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+       tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 
        return 0;
 }
 
-static void tg3_power_down(struct tg3 *tp)
+/* tp->lock is held. */
+static int tg3_load_tso_firmware(struct tg3 *tp)
 {
-       tg3_power_down_prepare(tp);
-
-       pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE));
-       pci_set_power_state(tp->pdev, PCI_D3hot);
-}
+       struct fw_info info;
+       const __be32 *fw_data;
+       unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
+       int err, i;
 
-static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
-{
-       switch (val & MII_TG3_AUX_STAT_SPDMASK) {
-       case MII_TG3_AUX_STAT_10HALF:
-               *speed = SPEED_10;
-               *duplex = DUPLEX_HALF;
-               break;
+       if (tg3_flag(tp, HW_TSO_1) ||
+           tg3_flag(tp, HW_TSO_2) ||
+           tg3_flag(tp, HW_TSO_3))
+               return 0;
 
-       case MII_TG3_AUX_STAT_10FULL:
-               *speed = SPEED_10;
-               *duplex = DUPLEX_FULL;
-               break;
+       fw_data = (void *)tp->fw->data;
 
-       case MII_TG3_AUX_STAT_100HALF:
-               *speed = SPEED_100;
-               *duplex = DUPLEX_HALF;
-               break;
+       /* Firmware blob starts with version numbers, followed by
+          start address and length. We are setting complete length.
+          length = end_address_of_bss - start_address_of_text.
+          Remainder is the blob to be loaded contiguously
+          from start address. */
 
-       case MII_TG3_AUX_STAT_100FULL:
-               *speed = SPEED_100;
-               *duplex = DUPLEX_FULL;
-               break;
+       info.fw_base = be32_to_cpu(fw_data[1]);
+       cpu_scratch_size = tp->fw_len;
+       info.fw_len = tp->fw->size - 12;
+       info.fw_data = &fw_data[3];
 
-       case MII_TG3_AUX_STAT_1000HALF:
-               *speed = SPEED_1000;
-               *duplex = DUPLEX_HALF;
-               break;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+               cpu_base = RX_CPU_BASE;
+               cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
+       } else {
+               cpu_base = TX_CPU_BASE;
+               cpu_scratch_base = TX_CPU_SCRATCH_BASE;
+               cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
+       }
 
-       case MII_TG3_AUX_STAT_1000FULL:
-               *speed = SPEED_1000;
-               *duplex = DUPLEX_FULL;
-               break;
+       err = tg3_load_firmware_cpu(tp, cpu_base,
+                                   cpu_scratch_base, cpu_scratch_size,
+                                   &info);
+       if (err)
+               return err;
 
-       default:
-               if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
-                       *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
-                                SPEED_10;
-                       *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
-                                 DUPLEX_HALF;
+       /* Now startup the cpu. */
+       tw32(cpu_base + CPU_STATE, 0xffffffff);
+       tw32_f(cpu_base + CPU_PC, info.fw_base);
+
+       for (i = 0; i < 5; i++) {
+               if (tr32(cpu_base + CPU_PC) == info.fw_base)
                        break;
-               }
-               *speed = SPEED_INVALID;
-               *duplex = DUPLEX_INVALID;
-               break;
+               tw32(cpu_base + CPU_STATE, 0xffffffff);
+               tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
+               tw32_f(cpu_base + CPU_PC, info.fw_base);
+               udelay(1000);
+       }
+       if (i >= 5) {
+               netdev_err(tp->dev,
+                          "%s fails to set CPU PC, is %08x should be %08x\n",
+                          __func__, tr32(cpu_base + CPU_PC), info.fw_base);
+               return -ENODEV;
        }
+       tw32(cpu_base + CPU_STATE, 0xffffffff);
+       tw32_f(cpu_base + CPU_MODE,  0x00000000);
+       return 0;
 }
 
-static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
-{
-       int err = 0;
-       u32 val, new_adv;
-
-       new_adv = ADVERTISE_CSMA;
-       new_adv |= ethtool_adv_to_mii_adv_t(advertise) & ADVERTISE_ALL;
-       new_adv |= mii_advertise_flowctrl(flowctrl);
-
-       err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
-       if (err)
-               goto done;
-
-       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
-               new_adv = ethtool_adv_to_mii_ctrl1000_t(advertise);
 
-               if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                   tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
-                       new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
+/* tp->lock is held. */
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{
+       u32 addr_high, addr_low;
+       int i;
 
-               err = tg3_writephy(tp, MII_CTRL1000, new_adv);
-               if (err)
-                       goto done;
+       addr_high = ((tp->dev->dev_addr[0] << 8) |
+                    tp->dev->dev_addr[1]);
+       addr_low = ((tp->dev->dev_addr[2] << 24) |
+                   (tp->dev->dev_addr[3] << 16) |
+                   (tp->dev->dev_addr[4] <<  8) |
+                   (tp->dev->dev_addr[5] <<  0));
+       for (i = 0; i < 4; i++) {
+               if (i == 1 && skip_mac_1)
+                       continue;
+               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
        }
 
-       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
-               goto done;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+               for (i = 0; i < 12; i++) {
+                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+               }
+       }
 
-       tw32(TG3_CPMU_EEE_MODE,
-            tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+       addr_high = (tp->dev->dev_addr[0] +
+                    tp->dev->dev_addr[1] +
+                    tp->dev->dev_addr[2] +
+                    tp->dev->dev_addr[3] +
+                    tp->dev->dev_addr[4] +
+                    tp->dev->dev_addr[5]) &
+               TX_BACKOFF_SEED_MASK;
+       tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
 
-       err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
-       if (!err) {
-               u32 err2;
+static void tg3_enable_register_access(struct tg3 *tp)
+{
+       /*
+        * Make sure register accesses (indirect or otherwise) will function
+        * correctly.
+        */
+       pci_write_config_dword(tp->pdev,
+                              TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+}
 
-               val = 0;
-               /* Advertise 100-BaseTX EEE ability */
-               if (advertise & ADVERTISED_100baseT_Full)
-                       val |= MDIO_AN_EEE_ADV_100TX;
-               /* Advertise 1000-BaseT EEE ability */
-               if (advertise & ADVERTISED_1000baseT_Full)
-                       val |= MDIO_AN_EEE_ADV_1000T;
-               err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
-               if (err)
-                       val = 0;
+static int tg3_power_up(struct tg3 *tp)
+{
+       int err;
 
-               switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
-               case ASIC_REV_5717:
-               case ASIC_REV_57765:
-               case ASIC_REV_57766:
-               case ASIC_REV_5719:
-                       /* If we advertised any eee advertisements above... */
-                       if (val)
-                               val = MII_TG3_DSP_TAP26_ALNOKO |
-                                     MII_TG3_DSP_TAP26_RMRXSTO |
-                                     MII_TG3_DSP_TAP26_OPCSINPT;
-                       tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
-                       /* Fall through */
-               case ASIC_REV_5720:
-                       if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
-                               tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
-                                                MII_TG3_DSP_CH34TP2_HIBW01);
-               }
+       tg3_enable_register_access(tp);
 
-               err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
-               if (!err)
-                       err = err2;
+       err = pci_set_power_state(tp->pdev, PCI_D0);
+       if (!err) {
+               /* Switch out of Vaux if it is a NIC */
+               tg3_pwrsrc_switch_to_vmain(tp);
+       } else {
+               netdev_err(tp->dev, "Transition to D0 failed\n");
        }
 
-done:
        return err;
 }
 
-static void tg3_phy_copper_begin(struct tg3 *tp)
+static int tg3_setup_phy(struct tg3 *, int);
+
+static int tg3_power_down_prepare(struct tg3 *tp)
 {
-       u32 new_adv;
-       int i;
+       u32 misc_host_ctrl;
+       bool device_should_wake, do_low_power;
 
-       if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
-               new_adv = ADVERTISED_10baseT_Half |
-                         ADVERTISED_10baseT_Full;
-               if (tg3_flag(tp, WOL_SPEED_100MB))
-                       new_adv |= ADVERTISED_100baseT_Half |
-                                  ADVERTISED_100baseT_Full;
-
-               tg3_phy_autoneg_cfg(tp, new_adv,
-                                   FLOW_CTRL_TX | FLOW_CTRL_RX);
-       } else if (tp->link_config.speed == SPEED_INVALID) {
-               if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
-                       tp->link_config.advertising &=
-                               ~(ADVERTISED_1000baseT_Half |
-                                 ADVERTISED_1000baseT_Full);
+       tg3_enable_register_access(tp);
 
-               tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
-                                   tp->link_config.flowctrl);
-       } else {
-               /* Asking for a specific link mode. */
-               if (tp->link_config.speed == SPEED_1000) {
-                       if (tp->link_config.duplex == DUPLEX_FULL)
-                               new_adv = ADVERTISED_1000baseT_Full;
-                       else
-                               new_adv = ADVERTISED_1000baseT_Half;
-               } else if (tp->link_config.speed == SPEED_100) {
-                       if (tp->link_config.duplex == DUPLEX_FULL)
-                               new_adv = ADVERTISED_100baseT_Full;
-                       else
-                               new_adv = ADVERTISED_100baseT_Half;
-               } else {
-                       if (tp->link_config.duplex == DUPLEX_FULL)
-                               new_adv = ADVERTISED_10baseT_Full;
-                       else
-                               new_adv = ADVERTISED_10baseT_Half;
-               }
+       /* Restore the CLKREQ setting. */
+       if (tg3_flag(tp, CLKREQ_BUG)) {
+               u16 lnkctl;
 
-               tg3_phy_autoneg_cfg(tp, new_adv,
-                                   tp->link_config.flowctrl);
+               pci_read_config_word(tp->pdev,
+                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
+                                    &lnkctl);
+               lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
+               pci_write_config_word(tp->pdev,
+                                     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
+                                     lnkctl);
        }
 
-       if (tp->link_config.autoneg == AUTONEG_DISABLE &&
-           tp->link_config.speed != SPEED_INVALID) {
-               u32 bmcr, orig_bmcr;
+       misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
+       tw32(TG3PCI_MISC_HOST_CTRL,
+            misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 
-               tp->link_config.active_speed = tp->link_config.speed;
-               tp->link_config.active_duplex = tp->link_config.duplex;
+       device_should_wake = device_may_wakeup(&tp->pdev->dev) &&
+                            tg3_flag(tp, WOL_ENABLE);
 
-               bmcr = 0;
-               switch (tp->link_config.speed) {
-               default:
-               case SPEED_10:
-                       break;
+       if (tg3_flag(tp, USE_PHYLIB)) {
+               do_low_power = false;
+               if ((tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) &&
+                   !(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
+                       struct phy_device *phydev;
+                       u32 phyid, advertising;
 
-               case SPEED_100:
-                       bmcr |= BMCR_SPEED100;
-                       break;
+                       phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 
-               case SPEED_1000:
-                       bmcr |= BMCR_SPEED1000;
-                       break;
-               }
+                       tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
 
-               if (tp->link_config.duplex == DUPLEX_FULL)
-                       bmcr |= BMCR_FULLDPLX;
+                       tp->link_config.speed = phydev->speed;
+                       tp->link_config.duplex = phydev->duplex;
+                       tp->link_config.autoneg = phydev->autoneg;
+                       tp->link_config.advertising = phydev->advertising;
 
-               if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) &&
-                   (bmcr != orig_bmcr)) {
-                       tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
-                       for (i = 0; i < 1500; i++) {
-                               u32 tmp;
+                       advertising = ADVERTISED_TP |
+                                     ADVERTISED_Pause |
+                                     ADVERTISED_Autoneg |
+                                     ADVERTISED_10baseT_Half;
 
-                               udelay(10);
-                               if (tg3_readphy(tp, MII_BMSR, &tmp) ||
-                                   tg3_readphy(tp, MII_BMSR, &tmp))
-                                       continue;
-                               if (!(tmp & BMSR_LSTATUS)) {
-                                       udelay(40);
-                                       break;
-                               }
+                       if (tg3_flag(tp, ENABLE_ASF) || device_should_wake) {
+                               if (tg3_flag(tp, WOL_SPEED_100MB))
+                                       advertising |=
+                                               ADVERTISED_100baseT_Half |
+                                               ADVERTISED_100baseT_Full |
+                                               ADVERTISED_10baseT_Full;
+                               else
+                                       advertising |= ADVERTISED_10baseT_Full;
+                       }
+
+                       phydev->advertising = advertising;
+
+                       phy_start_aneg(phydev);
+
+                       phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
+                       if (phyid != PHY_ID_BCMAC131) {
+                               phyid &= PHY_BCM_OUI_MASK;
+                               if (phyid == PHY_BCM_OUI_1 ||
+                                   phyid == PHY_BCM_OUI_2 ||
+                                   phyid == PHY_BCM_OUI_3)
+                                       do_low_power = true;
                        }
-                       tg3_writephy(tp, MII_BMCR, bmcr);
-                       udelay(40);
                }
        } else {
-               tg3_writephy(tp, MII_BMCR,
-                            BMCR_ANENABLE | BMCR_ANRESTART);
-       }
-}
+               do_low_power = true;
 
-static int tg3_init_5401phy_dsp(struct tg3 *tp)
-{
-       int err;
+               if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER))
+                       tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
 
-       /* Turn off tap power management. */
-       /* Set Extended packet length bit */
-       err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+               if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+                       tg3_setup_phy(tp, 0);
+       }
 
-       err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
-       err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
-       err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
-       err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
-       err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 val;
 
-       udelay(40);
+               val = tr32(GRC_VCPU_EXT_CTRL);
+               tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL);
+       } else if (!tg3_flag(tp, ENABLE_ASF)) {
+               int i;
+               u32 val;
 
-       return err;
-}
+               for (i = 0; i < 200; i++) {
+                       tg3_read_mem(tp, NIC_SRAM_FW_ASF_STATUS_MBOX, &val);
+                       if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+                               break;
+                       msleep(1);
+               }
+       }
+       if (tg3_flag(tp, WOL_CAP))
+               tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
+                                                    WOL_DRV_STATE_SHUTDOWN |
+                                                    WOL_DRV_WOL |
+                                                    WOL_SET_MAGIC_PKT);
 
-static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)
-{
-       u32 advmsk, tgtadv, advertising;
+       if (device_should_wake) {
+               u32 mac_mode;
 
-       advertising = tp->link_config.advertising;
-       tgtadv = ethtool_adv_to_mii_adv_t(advertising) & ADVERTISE_ALL;
+               if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
+                       if (do_low_power &&
+                           !(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
+                               tg3_phy_auxctl_write(tp,
+                                              MII_TG3_AUXCTL_SHDWSEL_PWRCTL,
+                                              MII_TG3_AUXCTL_PCTL_WOL_EN |
+                                              MII_TG3_AUXCTL_PCTL_100TX_LPWR |
+                                              MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC);
+                               udelay(40);
+                       }
 
-       advmsk = ADVERTISE_ALL;
-       if (tp->link_config.active_duplex == DUPLEX_FULL) {
-               tgtadv |= mii_advertise_flowctrl(tp->link_config.flowctrl);
-               advmsk |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-       }
+                       if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+                               mac_mode = MAC_MODE_PORT_MODE_GMII;
+                       else
+                               mac_mode = MAC_MODE_PORT_MODE_MII;
 
-       if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
-               return false;
+                       mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5700) {
+                               u32 speed = tg3_flag(tp, WOL_SPEED_100MB) ?
+                                            SPEED_100 : SPEED_10;
+                               if (tg3_5700_link_polarity(tp, speed))
+                                       mac_mode |= MAC_MODE_LINK_POLARITY;
+                               else
+                                       mac_mode &= ~MAC_MODE_LINK_POLARITY;
+                       }
+               } else {
+                       mac_mode = MAC_MODE_PORT_MODE_TBI;
+               }
 
-       if ((*lcladv & advmsk) != tgtadv)
-               return false;
+               if (!tg3_flag(tp, 5750_PLUS))
+                       tw32(MAC_LED_CTRL, tp->led_ctrl);
 
-       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
-               u32 tg3_ctrl;
+               mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+               if ((tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS)) &&
+                   (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)))
+                       mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
 
-               tgtadv = ethtool_adv_to_mii_ctrl1000_t(advertising);
+               if (tg3_flag(tp, ENABLE_APE))
+                       mac_mode |= MAC_MODE_APE_TX_EN |
+                                   MAC_MODE_APE_RX_EN |
+                                   MAC_MODE_TDE_ENABLE;
 
-               if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
-                       return false;
+               tw32_f(MAC_MODE, mac_mode);
+               udelay(100);
 
-               tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
-               if (tg3_ctrl != tgtadv)
-                       return false;
+               tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
+               udelay(10);
        }
 
-       return true;
-}
+       if (!tg3_flag(tp, WOL_SPEED_100MB) &&
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
+               u32 base_val;
 
-static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
-{
-       u32 lpeth = 0;
+               base_val = tp->pci_clock_ctrl;
+               base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
+                            CLOCK_CTRL_TXCLK_DISABLE);
 
-       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
-               u32 val;
+               tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
+                           CLOCK_CTRL_PWRDOWN_PLL133, 40);
+       } else if (tg3_flag(tp, 5780_CLASS) ||
+                  tg3_flag(tp, CPMU_PRESENT) ||
+                  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               /* do nothing */
+       } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) {
+               u32 newbits1, newbits2;
 
-               if (tg3_readphy(tp, MII_STAT1000, &val))
-                       return false;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+                       newbits1 = (CLOCK_CTRL_RXCLK_DISABLE |
+                                   CLOCK_CTRL_TXCLK_DISABLE |
+                                   CLOCK_CTRL_ALTCLK);
+                       newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
+               } else if (tg3_flag(tp, 5705_PLUS)) {
+                       newbits1 = CLOCK_CTRL_625_CORE;
+                       newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
+               } else {
+                       newbits1 = CLOCK_CTRL_ALTCLK;
+                       newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
+               }
 
-               lpeth = mii_stat1000_to_ethtool_lpa_t(val);
-       }
+               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1,
+                           40);
 
-       if (tg3_readphy(tp, MII_LPA, rmtadv))
-               return false;
+               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2,
+                           40);
 
-       lpeth |= mii_lpa_to_ethtool_lpa_t(*rmtadv);
-       tp->link_config.rmt_adv = lpeth;
+               if (!tg3_flag(tp, 5705_PLUS)) {
+                       u32 newbits3;
 
-       return true;
-}
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+                               newbits3 = (CLOCK_CTRL_RXCLK_DISABLE |
+                                           CLOCK_CTRL_TXCLK_DISABLE |
+                                           CLOCK_CTRL_44MHZ_CORE);
+                       } else {
+                               newbits3 = CLOCK_CTRL_44MHZ_CORE;
+                       }
 
-static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
-{
-       int current_link_up;
-       u32 bmsr, val;
-       u32 lcl_adv, rmt_adv;
-       u16 current_speed;
-       u8 current_duplex;
-       int i, err;
+                       tw32_wait_f(TG3PCI_CLOCK_CTRL,
+                                   tp->pci_clock_ctrl | newbits3, 40);
+               }
+       }
 
-       tw32(MAC_EVENT, 0);
+       if (!(device_should_wake) && !tg3_flag(tp, ENABLE_ASF))
+               tg3_power_down_phy(tp, do_low_power);
 
-       tw32_f(MAC_STATUS,
-            (MAC_STATUS_SYNC_CHANGED |
-             MAC_STATUS_CFG_CHANGED |
-             MAC_STATUS_MI_COMPLETION |
-             MAC_STATUS_LNKSTATE_CHANGED));
-       udelay(40);
+       tg3_frob_aux_power(tp, true);
 
-       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-               tw32_f(MAC_MI_MODE,
-                    (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-               udelay(80);
-       }
+       /* Workaround for unstable PLL clock */
+       if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
+           (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
+               u32 val = tr32(0x7d00);
 
-       tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
+               val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
+               tw32(0x7d00, val);
+               if (!tg3_flag(tp, ENABLE_ASF)) {
+                       int err;
 
-       /* Some third-party PHYs need to be reset on link going
-        * down.
-        */
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
-           netif_carrier_ok(tp->dev)) {
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
-                   !(bmsr & BMSR_LSTATUS))
-                       force_reset = 1;
+                       err = tg3_nvram_lock(tp);
+                       tg3_halt_cpu(tp, RX_CPU_BASE);
+                       if (!err)
+                               tg3_nvram_unlock(tp);
+               }
        }
-       if (force_reset)
-               tg3_phy_reset(tp);
 
-       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
-                   !tg3_flag(tp, INIT_COMPLETE))
-                       bmsr = 0;
+       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
-               if (!(bmsr & BMSR_LSTATUS)) {
-                       err = tg3_init_5401phy_dsp(tp);
-                       if (err)
-                               return err;
+       return 0;
+}
 
-                       tg3_readphy(tp, MII_BMSR, &bmsr);
-                       for (i = 0; i < 1000; i++) {
-                               udelay(10);
-                               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
-                                   (bmsr & BMSR_LSTATUS)) {
-                                       udelay(40);
-                                       break;
-                               }
-                       }
+static void tg3_power_down(struct tg3 *tp)
+{
+       tg3_power_down_prepare(tp);
 
-                       if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
-                           TG3_PHY_REV_BCM5401_B0 &&
-                           !(bmsr & BMSR_LSTATUS) &&
-                           tp->link_config.active_speed == SPEED_1000) {
-                               err = tg3_phy_reset(tp);
-                               if (!err)
-                                       err = tg3_init_5401phy_dsp(tp);
-                               if (err)
-                                       return err;
-                       }
-               }
-       } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                  tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
-               /* 5701 {A0,B0} CRC bug workaround */
-               tg3_writephy(tp, 0x15, 0x0a75);
-               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
-               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
-               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
-       }
+       pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE));
+       pci_set_power_state(tp->pdev, PCI_D3hot);
+}
 
-       /* Clear pending interrupts... */
-       tg3_readphy(tp, MII_TG3_ISTAT, &val);
-       tg3_readphy(tp, MII_TG3_ISTAT, &val);
+static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
+{
+       switch (val & MII_TG3_AUX_STAT_SPDMASK) {
+       case MII_TG3_AUX_STAT_10HALF:
+               *speed = SPEED_10;
+               *duplex = DUPLEX_HALF;
+               break;
 
-       if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
-               tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
-       else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
-               tg3_writephy(tp, MII_TG3_IMASK, ~0);
+       case MII_TG3_AUX_STAT_10FULL:
+               *speed = SPEED_10;
+               *duplex = DUPLEX_FULL;
+               break;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-               if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
-                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
-                                    MII_TG3_EXT_CTRL_LNK3_LED_MODE);
-               else
-                       tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
-       }
+       case MII_TG3_AUX_STAT_100HALF:
+               *speed = SPEED_100;
+               *duplex = DUPLEX_HALF;
+               break;
 
-       current_link_up = 0;
-       current_speed = SPEED_INVALID;
-       current_duplex = DUPLEX_INVALID;
-       tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
-       tp->link_config.rmt_adv = 0;
+       case MII_TG3_AUX_STAT_100FULL:
+               *speed = SPEED_100;
+               *duplex = DUPLEX_FULL;
+               break;
 
-       if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
-               err = tg3_phy_auxctl_read(tp,
-                                         MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
-                                         &val);
-               if (!err && !(val & (1 << 10))) {
-                       tg3_phy_auxctl_write(tp,
-                                            MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
-                                            val | (1 << 10));
-                       goto relink;
-               }
-       }
+       case MII_TG3_AUX_STAT_1000HALF:
+               *speed = SPEED_1000;
+               *duplex = DUPLEX_HALF;
+               break;
 
-       bmsr = 0;
-       for (i = 0; i < 100; i++) {
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
-                   (bmsr & BMSR_LSTATUS))
+       case MII_TG3_AUX_STAT_1000FULL:
+               *speed = SPEED_1000;
+               *duplex = DUPLEX_FULL;
+               break;
+
+       default:
+               if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+                       *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+                                SPEED_10;
+                       *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+                                 DUPLEX_HALF;
                        break;
-               udelay(40);
+               }
+               *speed = SPEED_UNKNOWN;
+               *duplex = DUPLEX_UNKNOWN;
+               break;
        }
+}
 
-       if (bmsr & BMSR_LSTATUS) {
-               u32 aux_stat, bmcr;
+static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
+{
+       int err = 0;
+       u32 val, new_adv;
 
-               tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
-               for (i = 0; i < 2000; i++) {
-                       udelay(10);
-                       if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
-                           aux_stat)
-                               break;
-               }
+       new_adv = ADVERTISE_CSMA;
+       new_adv |= ethtool_adv_to_mii_adv_t(advertise) & ADVERTISE_ALL;
+       new_adv |= mii_advertise_flowctrl(flowctrl);
 
-               tg3_aux_stat_to_speed_duplex(tp, aux_stat,
-                                            &current_speed,
-                                            &current_duplex);
+       err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
+       if (err)
+               goto done;
 
-               bmcr = 0;
-               for (i = 0; i < 200; i++) {
-                       tg3_readphy(tp, MII_BMCR, &bmcr);
-                       if (tg3_readphy(tp, MII_BMCR, &bmcr))
-                               continue;
-                       if (bmcr && bmcr != 0x7fff)
-                               break;
-                       udelay(10);
-               }
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+               new_adv = ethtool_adv_to_mii_ctrl1000_t(advertise);
 
-               lcl_adv = 0;
-               rmt_adv = 0;
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+                   tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+                       new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
 
-               tp->link_config.active_speed = current_speed;
-               tp->link_config.active_duplex = current_duplex;
+               err = tg3_writephy(tp, MII_CTRL1000, new_adv);
+               if (err)
+                       goto done;
+       }
 
-               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-                       if ((bmcr & BMCR_ANENABLE) &&
-                           tg3_phy_copper_an_config_ok(tp, &lcl_adv) &&
-                           tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv))
-                               current_link_up = 1;
-               } else {
-                       if (!(bmcr & BMCR_ANENABLE) &&
-                           tp->link_config.speed == current_speed &&
-                           tp->link_config.duplex == current_duplex &&
-                           tp->link_config.flowctrl ==
-                           tp->link_config.active_flowctrl) {
-                               current_link_up = 1;
-                       }
-               }
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+               goto done;
 
-               if (current_link_up == 1 &&
-                   tp->link_config.active_duplex == DUPLEX_FULL) {
-                       u32 reg, bit;
+       tw32(TG3_CPMU_EEE_MODE,
+            tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 
-                       if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
-                               reg = MII_TG3_FET_GEN_STAT;
-                               bit = MII_TG3_FET_GEN_STAT_MDIXSTAT;
-                       } else {
-                               reg = MII_TG3_EXT_STAT;
-                               bit = MII_TG3_EXT_STAT_MDIX;
-                       }
+       err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+       if (!err) {
+               u32 err2;
 
-                       if (!tg3_readphy(tp, reg, &val) && (val & bit))
-                               tp->phy_flags |= TG3_PHYFLG_MDIX_STATE;
+               val = 0;
+               /* Advertise 100-BaseTX EEE ability */
+               if (advertise & ADVERTISED_100baseT_Full)
+                       val |= MDIO_AN_EEE_ADV_100TX;
+               /* Advertise 1000-BaseT EEE ability */
+               if (advertise & ADVERTISED_1000baseT_Full)
+                       val |= MDIO_AN_EEE_ADV_1000T;
+               err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+               if (err)
+                       val = 0;
 
-                       tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
+               switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+               case ASIC_REV_5717:
+               case ASIC_REV_57765:
+               case ASIC_REV_57766:
+               case ASIC_REV_5719:
+                       /* If we advertised any eee advertisements above... */
+                       if (val)
+                               val = MII_TG3_DSP_TAP26_ALNOKO |
+                                     MII_TG3_DSP_TAP26_RMRXSTO |
+                                     MII_TG3_DSP_TAP26_OPCSINPT;
+                       tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
+                       /* Fall through */
+               case ASIC_REV_5720:
+                       if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+                               tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
+                                                MII_TG3_DSP_CH34TP2_HIBW01);
                }
+
+               err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               if (!err)
+                       err = err2;
        }
 
-relink:
-       if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
-               tg3_phy_copper_begin(tp);
+done:
+       return err;
+}
 
-               tg3_readphy(tp, MII_BMSR, &bmsr);
-               if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
-                   (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
-                       current_link_up = 1;
-       }
+static void tg3_phy_copper_begin(struct tg3 *tp)
+{
+       if (tp->link_config.autoneg == AUTONEG_ENABLE ||
+           (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
+               u32 adv, fc;
 
-       tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
-       if (current_link_up == 1) {
-               if (tp->link_config.active_speed == SPEED_100 ||
-                   tp->link_config.active_speed == SPEED_10)
-                       tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
-               else
-                       tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
-       } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
-               tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
-       else
-               tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+               if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+                       adv = ADVERTISED_10baseT_Half |
+                             ADVERTISED_10baseT_Full;
+                       if (tg3_flag(tp, WOL_SPEED_100MB))
+                               adv |= ADVERTISED_100baseT_Half |
+                                      ADVERTISED_100baseT_Full;
 
-       tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
-       if (tp->link_config.active_duplex == DUPLEX_HALF)
-               tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
+                       fc = FLOW_CTRL_TX | FLOW_CTRL_RX;
+               } else {
+                       adv = tp->link_config.advertising;
+                       if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+                               adv &= ~(ADVERTISED_1000baseT_Half |
+                                        ADVERTISED_1000baseT_Full);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
-               if (current_link_up == 1 &&
-                   tg3_5700_link_polarity(tp, tp->link_config.active_speed))
-                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
-               else
-                       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-       }
+                       fc = tp->link_config.flowctrl;
+               }
 
-       /* ??? Without this setting Netgear GA302T PHY does not
-        * ??? send/receive packets...
-        */
-       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
-           tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
-               tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
-               tw32_f(MAC_MI_MODE, tp->mi_mode);
-               udelay(80);
-       }
+               tg3_phy_autoneg_cfg(tp, adv, fc);
 
-       tw32_f(MAC_MODE, tp->mac_mode);
-       udelay(40);
+               tg3_writephy(tp, MII_BMCR,
+                            BMCR_ANENABLE | BMCR_ANRESTART);
+       } else {
+               int i;
+               u32 bmcr, orig_bmcr;
 
-       tg3_phy_eee_adjust(tp, current_link_up);
+               tp->link_config.active_speed = tp->link_config.speed;
+               tp->link_config.active_duplex = tp->link_config.duplex;
 
-       if (tg3_flag(tp, USE_LINKCHG_REG)) {
-               /* Polled via timer. */
-               tw32_f(MAC_EVENT, 0);
-       } else {
-               tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-       }
-       udelay(40);
+               bmcr = 0;
+               switch (tp->link_config.speed) {
+               default:
+               case SPEED_10:
+                       break;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
-           current_link_up == 1 &&
-           tp->link_config.active_speed == SPEED_1000 &&
-           (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
-               udelay(120);
-               tw32_f(MAC_STATUS,
-                    (MAC_STATUS_SYNC_CHANGED |
-                     MAC_STATUS_CFG_CHANGED));
-               udelay(40);
-               tg3_write_mem(tp,
-                             NIC_SRAM_FIRMWARE_MBOX,
-                             NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
-       }
+               case SPEED_100:
+                       bmcr |= BMCR_SPEED100;
+                       break;
 
-       /* Prevent send BD corruption. */
-       if (tg3_flag(tp, CLKREQ_BUG)) {
-               u16 oldlnkctl, newlnkctl;
+               case SPEED_1000:
+                       bmcr |= BMCR_SPEED1000;
+                       break;
+               }
 
-               pci_read_config_word(tp->pdev,
-                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                    &oldlnkctl);
-               if (tp->link_config.active_speed == SPEED_100 ||
-                   tp->link_config.active_speed == SPEED_10)
-                       newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
-               else
-                       newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
-               if (newlnkctl != oldlnkctl)
-                       pci_write_config_word(tp->pdev,
-                                             pci_pcie_cap(tp->pdev) +
-                                             PCI_EXP_LNKCTL, newlnkctl);
-       }
+               if (tp->link_config.duplex == DUPLEX_FULL)
+                       bmcr |= BMCR_FULLDPLX;
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else
-                       netif_carrier_off(tp->dev);
-               tg3_link_report(tp);
-       }
+               if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) &&
+                   (bmcr != orig_bmcr)) {
+                       tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
+                       for (i = 0; i < 1500; i++) {
+                               u32 tmp;
 
-       return 0;
+                               udelay(10);
+                               if (tg3_readphy(tp, MII_BMSR, &tmp) ||
+                                   tg3_readphy(tp, MII_BMSR, &tmp))
+                                       continue;
+                               if (!(tmp & BMSR_LSTATUS)) {
+                                       udelay(40);
+                                       break;
+                               }
+                       }
+                       tg3_writephy(tp, MII_BMCR, bmcr);
+                       udelay(40);
+               }
+       }
 }
 
-struct tg3_fiber_aneginfo {
-       int state;
-#define ANEG_STATE_UNKNOWN             0
-#define ANEG_STATE_AN_ENABLE           1
-#define ANEG_STATE_RESTART_INIT                2
-#define ANEG_STATE_RESTART             3
-#define ANEG_STATE_DISABLE_LINK_OK     4
-#define ANEG_STATE_ABILITY_DETECT_INIT 5
-#define ANEG_STATE_ABILITY_DETECT      6
-#define ANEG_STATE_ACK_DETECT_INIT     7
-#define ANEG_STATE_ACK_DETECT          8
-#define ANEG_STATE_COMPLETE_ACK_INIT   9
-#define ANEG_STATE_COMPLETE_ACK                10
-#define ANEG_STATE_IDLE_DETECT_INIT    11
-#define ANEG_STATE_IDLE_DETECT         12
-#define ANEG_STATE_LINK_OK             13
-#define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14
-#define ANEG_STATE_NEXT_PAGE_WAIT      15
+static int tg3_init_5401phy_dsp(struct tg3 *tp)
+{
+       int err;
 
-       u32 flags;
-#define MR_AN_ENABLE           0x00000001
-#define MR_RESTART_AN          0x00000002
-#define MR_AN_COMPLETE         0x00000004
-#define MR_PAGE_RX             0x00000008
-#define MR_NP_LOADED           0x00000010
-#define MR_TOGGLE_TX           0x00000020
-#define MR_LP_ADV_FULL_DUPLEX  0x00000040
-#define MR_LP_ADV_HALF_DUPLEX  0x00000080
-#define MR_LP_ADV_SYM_PAUSE    0x00000100
-#define MR_LP_ADV_ASYM_PAUSE   0x00000200
-#define MR_LP_ADV_REMOTE_FAULT1        0x00000400
-#define MR_LP_ADV_REMOTE_FAULT2        0x00000800
-#define MR_LP_ADV_NEXT_PAGE    0x00001000
-#define MR_TOGGLE_RX           0x00002000
-#define MR_NP_RX               0x00004000
+       /* Turn off tap power management. */
+       /* Set Extended packet length bit */
+       err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
 
-#define MR_LINK_OK             0x80000000
+       err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
+       err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
+       err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
+       err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
+       err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
 
-       unsigned long link_time, cur_time;
+       udelay(40);
 
-       u32 ability_match_cfg;
-       int ability_match_count;
+       return err;
+}
 
-       char ability_match, idle_match, ack_match;
+static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)
+{
+       u32 advmsk, tgtadv, advertising;
 
-       u32 txconfig, rxconfig;
-#define ANEG_CFG_NP            0x00000080
-#define ANEG_CFG_ACK           0x00000040
-#define ANEG_CFG_RF2           0x00000020
-#define ANEG_CFG_RF1           0x00000010
-#define ANEG_CFG_PS2           0x00000001
-#define ANEG_CFG_PS1           0x00008000
-#define ANEG_CFG_HD            0x00004000
-#define ANEG_CFG_FD            0x00002000
-#define ANEG_CFG_INVAL         0x00001f06
+       advertising = tp->link_config.advertising;
+       tgtadv = ethtool_adv_to_mii_adv_t(advertising) & ADVERTISE_ALL;
 
-};
-#define ANEG_OK                0
-#define ANEG_DONE      1
-#define ANEG_TIMER_ENAB        2
-#define ANEG_FAILED    -1
+       advmsk = ADVERTISE_ALL;
+       if (tp->link_config.active_duplex == DUPLEX_FULL) {
+               tgtadv |= mii_advertise_flowctrl(tp->link_config.flowctrl);
+               advmsk |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+       }
 
-#define ANEG_STATE_SETTLE_TIME 10000
+       if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
+               return false;
 
-static int tg3_fiber_aneg_smachine(struct tg3 *tp,
-                                  struct tg3_fiber_aneginfo *ap)
-{
-       u16 flowctrl;
-       unsigned long delta;
-       u32 rx_cfg_reg;
-       int ret;
+       if ((*lcladv & advmsk) != tgtadv)
+               return false;
 
-       if (ap->state == ANEG_STATE_UNKNOWN) {
-               ap->rxconfig = 0;
-               ap->link_time = 0;
-               ap->cur_time = 0;
-               ap->ability_match_cfg = 0;
-               ap->ability_match_count = 0;
-               ap->ability_match = 0;
-               ap->idle_match = 0;
-               ap->ack_match = 0;
-       }
-       ap->cur_time++;
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+               u32 tg3_ctrl;
 
-       if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
-               rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
+               tgtadv = ethtool_adv_to_mii_ctrl1000_t(advertising);
 
-               if (rx_cfg_reg != ap->ability_match_cfg) {
-                       ap->ability_match_cfg = rx_cfg_reg;
-                       ap->ability_match = 0;
-                       ap->ability_match_count = 0;
+               if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
+                       return false;
+
+               if (tgtadv &&
+                   (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+                    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) {
+                       tgtadv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
+                       tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL |
+                                    CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
                } else {
-                       if (++ap->ability_match_count > 1) {
-                               ap->ability_match = 1;
-                               ap->ability_match_cfg = rx_cfg_reg;
-                       }
+                       tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
                }
-               if (rx_cfg_reg & ANEG_CFG_ACK)
-                       ap->ack_match = 1;
-               else
-                       ap->ack_match = 0;
-
-               ap->idle_match = 0;
-       } else {
-               ap->idle_match = 1;
-               ap->ability_match_cfg = 0;
-               ap->ability_match_count = 0;
-               ap->ability_match = 0;
-               ap->ack_match = 0;
 
-               rx_cfg_reg = 0;
+               if (tg3_ctrl != tgtadv)
+                       return false;
        }
 
-       ap->rxconfig = rx_cfg_reg;
-       ret = ANEG_OK;
+       return true;
+}
 
-       switch (ap->state) {
-       case ANEG_STATE_UNKNOWN:
-               if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
-                       ap->state = ANEG_STATE_AN_ENABLE;
+static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
+{
+       u32 lpeth = 0;
 
-               /* fallthru */
-       case ANEG_STATE_AN_ENABLE:
-               ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
-               if (ap->flags & MR_AN_ENABLE) {
-                       ap->link_time = 0;
-                       ap->cur_time = 0;
-                       ap->ability_match_cfg = 0;
-                       ap->ability_match_count = 0;
-                       ap->ability_match = 0;
-                       ap->idle_match = 0;
-                       ap->ack_match = 0;
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+               u32 val;
 
-                       ap->state = ANEG_STATE_RESTART_INIT;
-               } else {
-                       ap->state = ANEG_STATE_DISABLE_LINK_OK;
-               }
-               break;
+               if (tg3_readphy(tp, MII_STAT1000, &val))
+                       return false;
+
+               lpeth = mii_stat1000_to_ethtool_lpa_t(val);
+       }
+
+       if (tg3_readphy(tp, MII_LPA, rmtadv))
+               return false;
+
+       lpeth |= mii_lpa_to_ethtool_lpa_t(*rmtadv);
+       tp->link_config.rmt_adv = lpeth;
+
+       return true;
+}
+
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
+{
+       int current_link_up;
+       u32 bmsr, val;
+       u32 lcl_adv, rmt_adv;
+       u16 current_speed;
+       u8 current_duplex;
+       int i, err;
+
+       tw32(MAC_EVENT, 0);
+
+       tw32_f(MAC_STATUS,
+            (MAC_STATUS_SYNC_CHANGED |
+             MAC_STATUS_CFG_CHANGED |
+             MAC_STATUS_MI_COMPLETION |
+             MAC_STATUS_LNKSTATE_CHANGED));
+       udelay(40);
+
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE,
+                    (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+               udelay(80);
+       }
+
+       tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
+
+       /* Some third-party PHYs need to be reset on link going
+        * down.
+        */
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
+           netif_carrier_ok(tp->dev)) {
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                   !(bmsr & BMSR_LSTATUS))
+                       force_reset = 1;
+       }
+       if (force_reset)
+               tg3_phy_reset(tp);
+
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
+                   !tg3_flag(tp, INIT_COMPLETE))
+                       bmsr = 0;
+
+               if (!(bmsr & BMSR_LSTATUS)) {
+                       err = tg3_init_5401phy_dsp(tp);
+                       if (err)
+                               return err;
+
+                       tg3_readphy(tp, MII_BMSR, &bmsr);
+                       for (i = 0; i < 1000; i++) {
+                               udelay(10);
+                               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                                   (bmsr & BMSR_LSTATUS)) {
+                                       udelay(40);
+                                       break;
+                               }
+                       }
+
+                       if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
+                           TG3_PHY_REV_BCM5401_B0 &&
+                           !(bmsr & BMSR_LSTATUS) &&
+                           tp->link_config.active_speed == SPEED_1000) {
+                               err = tg3_phy_reset(tp);
+                               if (!err)
+                                       err = tg3_init_5401phy_dsp(tp);
+                               if (err)
+                                       return err;
+                       }
+               }
+       } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+                  tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
+               /* 5701 {A0,B0} CRC bug workaround */
+               tg3_writephy(tp, 0x15, 0x0a75);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+               tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+       }
+
+       /* Clear pending interrupts... */
+       tg3_readphy(tp, MII_TG3_ISTAT, &val);
+       tg3_readphy(tp, MII_TG3_ISTAT, &val);
+
+       if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
+               tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
+       else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
+               tg3_writephy(tp, MII_TG3_IMASK, ~0);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+               if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                                    MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+               else
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
+       }
+
+       current_link_up = 0;
+       current_speed = SPEED_UNKNOWN;
+       current_duplex = DUPLEX_UNKNOWN;
+       tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
+       tp->link_config.rmt_adv = 0;
+
+       if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
+               err = tg3_phy_auxctl_read(tp,
+                                         MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+                                         &val);
+               if (!err && !(val & (1 << 10))) {
+                       tg3_phy_auxctl_write(tp,
+                                            MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+                                            val | (1 << 10));
+                       goto relink;
+               }
+       }
+
+       bmsr = 0;
+       for (i = 0; i < 100; i++) {
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+                   (bmsr & BMSR_LSTATUS))
+                       break;
+               udelay(40);
+       }
+
+       if (bmsr & BMSR_LSTATUS) {
+               u32 aux_stat, bmcr;
+
+               tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
+               for (i = 0; i < 2000; i++) {
+                       udelay(10);
+                       if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
+                           aux_stat)
+                               break;
+               }
+
+               tg3_aux_stat_to_speed_duplex(tp, aux_stat,
+                                            &current_speed,
+                                            &current_duplex);
+
+               bmcr = 0;
+               for (i = 0; i < 200; i++) {
+                       tg3_readphy(tp, MII_BMCR, &bmcr);
+                       if (tg3_readphy(tp, MII_BMCR, &bmcr))
+                               continue;
+                       if (bmcr && bmcr != 0x7fff)
+                               break;
+                       udelay(10);
+               }
+
+               lcl_adv = 0;
+               rmt_adv = 0;
+
+               tp->link_config.active_speed = current_speed;
+               tp->link_config.active_duplex = current_duplex;
+
+               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+                       if ((bmcr & BMCR_ANENABLE) &&
+                           tg3_phy_copper_an_config_ok(tp, &lcl_adv) &&
+                           tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv))
+                               current_link_up = 1;
+               } else {
+                       if (!(bmcr & BMCR_ANENABLE) &&
+                           tp->link_config.speed == current_speed &&
+                           tp->link_config.duplex == current_duplex &&
+                           tp->link_config.flowctrl ==
+                           tp->link_config.active_flowctrl) {
+                               current_link_up = 1;
+                       }
+               }
+
+               if (current_link_up == 1 &&
+                   tp->link_config.active_duplex == DUPLEX_FULL) {
+                       u32 reg, bit;
+
+                       if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+                               reg = MII_TG3_FET_GEN_STAT;
+                               bit = MII_TG3_FET_GEN_STAT_MDIXSTAT;
+                       } else {
+                               reg = MII_TG3_EXT_STAT;
+                               bit = MII_TG3_EXT_STAT_MDIX;
+                       }
+
+                       if (!tg3_readphy(tp, reg, &val) && (val & bit))
+                               tp->phy_flags |= TG3_PHYFLG_MDIX_STATE;
+
+                       tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
+               }
+       }
+
+relink:
+       if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
+               tg3_phy_copper_begin(tp);
+
+               tg3_readphy(tp, MII_BMSR, &bmsr);
+               if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
+                   (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
+                       current_link_up = 1;
+       }
+
+       tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
+       if (current_link_up == 1) {
+               if (tp->link_config.active_speed == SPEED_100 ||
+                   tp->link_config.active_speed == SPEED_10)
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+               else
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+       } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+               tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+       else
+               tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
+       tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
+       if (tp->link_config.active_duplex == DUPLEX_HALF)
+               tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+               if (current_link_up == 1 &&
+                   tg3_5700_link_polarity(tp, tp->link_config.active_speed))
+                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+               else
+                       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+       }
+
+       /* ??? Without this setting Netgear GA302T PHY does not
+        * ??? send/receive packets...
+        */
+       if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
+           tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
+               tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
+               tw32_f(MAC_MI_MODE, tp->mi_mode);
+               udelay(80);
+       }
+
+       tw32_f(MAC_MODE, tp->mac_mode);
+       udelay(40);
+
+       tg3_phy_eee_adjust(tp, current_link_up);
+
+       if (tg3_flag(tp, USE_LINKCHG_REG)) {
+               /* Polled via timer. */
+               tw32_f(MAC_EVENT, 0);
+       } else {
+               tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+       }
+       udelay(40);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
+           current_link_up == 1 &&
+           tp->link_config.active_speed == SPEED_1000 &&
+           (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
+               udelay(120);
+               tw32_f(MAC_STATUS,
+                    (MAC_STATUS_SYNC_CHANGED |
+                     MAC_STATUS_CFG_CHANGED));
+               udelay(40);
+               tg3_write_mem(tp,
+                             NIC_SRAM_FIRMWARE_MBOX,
+                             NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
+       }
+
+       /* Prevent send BD corruption. */
+       if (tg3_flag(tp, CLKREQ_BUG)) {
+               u16 oldlnkctl, newlnkctl;
+
+               pci_read_config_word(tp->pdev,
+                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
+                                    &oldlnkctl);
+               if (tp->link_config.active_speed == SPEED_100 ||
+                   tp->link_config.active_speed == SPEED_10)
+                       newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+               else
+                       newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+               if (newlnkctl != oldlnkctl)
+                       pci_write_config_word(tp->pdev,
+                                             pci_pcie_cap(tp->pdev) +
+                                             PCI_EXP_LNKCTL, newlnkctl);
+       }
+
+       if (current_link_up != netif_carrier_ok(tp->dev)) {
+               if (current_link_up)
+                       netif_carrier_on(tp->dev);
+               else
+                       netif_carrier_off(tp->dev);
+               tg3_link_report(tp);
+       }
+
+       return 0;
+}
+
+struct tg3_fiber_aneginfo {
+       int state;
+#define ANEG_STATE_UNKNOWN             0
+#define ANEG_STATE_AN_ENABLE           1
+#define ANEG_STATE_RESTART_INIT                2
+#define ANEG_STATE_RESTART             3
+#define ANEG_STATE_DISABLE_LINK_OK     4
+#define ANEG_STATE_ABILITY_DETECT_INIT 5
+#define ANEG_STATE_ABILITY_DETECT      6
+#define ANEG_STATE_ACK_DETECT_INIT     7
+#define ANEG_STATE_ACK_DETECT          8
+#define ANEG_STATE_COMPLETE_ACK_INIT   9
+#define ANEG_STATE_COMPLETE_ACK                10
+#define ANEG_STATE_IDLE_DETECT_INIT    11
+#define ANEG_STATE_IDLE_DETECT         12
+#define ANEG_STATE_LINK_OK             13
+#define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14
+#define ANEG_STATE_NEXT_PAGE_WAIT      15
+
+       u32 flags;
+#define MR_AN_ENABLE           0x00000001
+#define MR_RESTART_AN          0x00000002
+#define MR_AN_COMPLETE         0x00000004
+#define MR_PAGE_RX             0x00000008
+#define MR_NP_LOADED           0x00000010
+#define MR_TOGGLE_TX           0x00000020
+#define MR_LP_ADV_FULL_DUPLEX  0x00000040
+#define MR_LP_ADV_HALF_DUPLEX  0x00000080
+#define MR_LP_ADV_SYM_PAUSE    0x00000100
+#define MR_LP_ADV_ASYM_PAUSE   0x00000200
+#define MR_LP_ADV_REMOTE_FAULT1        0x00000400
+#define MR_LP_ADV_REMOTE_FAULT2        0x00000800
+#define MR_LP_ADV_NEXT_PAGE    0x00001000
+#define MR_TOGGLE_RX           0x00002000
+#define MR_NP_RX               0x00004000
+
+#define MR_LINK_OK             0x80000000
+
+       unsigned long link_time, cur_time;
+
+       u32 ability_match_cfg;
+       int ability_match_count;
+
+       char ability_match, idle_match, ack_match;
+
+       u32 txconfig, rxconfig;
+#define ANEG_CFG_NP            0x00000080
+#define ANEG_CFG_ACK           0x00000040
+#define ANEG_CFG_RF2           0x00000020
+#define ANEG_CFG_RF1           0x00000010
+#define ANEG_CFG_PS2           0x00000001
+#define ANEG_CFG_PS1           0x00008000
+#define ANEG_CFG_HD            0x00004000
+#define ANEG_CFG_FD            0x00002000
+#define ANEG_CFG_INVAL         0x00001f06
+
+};
+#define ANEG_OK                0
+#define ANEG_DONE      1
+#define ANEG_TIMER_ENAB        2
+#define ANEG_FAILED    -1
+
+#define ANEG_STATE_SETTLE_TIME 10000
+
+static int tg3_fiber_aneg_smachine(struct tg3 *tp,
+                                  struct tg3_fiber_aneginfo *ap)
+{
+       u16 flowctrl;
+       unsigned long delta;
+       u32 rx_cfg_reg;
+       int ret;
+
+       if (ap->state == ANEG_STATE_UNKNOWN) {
+               ap->rxconfig = 0;
+               ap->link_time = 0;
+               ap->cur_time = 0;
+               ap->ability_match_cfg = 0;
+               ap->ability_match_count = 0;
+               ap->ability_match = 0;
+               ap->idle_match = 0;
+               ap->ack_match = 0;
+       }
+       ap->cur_time++;
+
+       if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
+               rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
+
+               if (rx_cfg_reg != ap->ability_match_cfg) {
+                       ap->ability_match_cfg = rx_cfg_reg;
+                       ap->ability_match = 0;
+                       ap->ability_match_count = 0;
+               } else {
+                       if (++ap->ability_match_count > 1) {
+                               ap->ability_match = 1;
+                               ap->ability_match_cfg = rx_cfg_reg;
+                       }
+               }
+               if (rx_cfg_reg & ANEG_CFG_ACK)
+                       ap->ack_match = 1;
+               else
+                       ap->ack_match = 0;
+
+               ap->idle_match = 0;
+       } else {
+               ap->idle_match = 1;
+               ap->ability_match_cfg = 0;
+               ap->ability_match_count = 0;
+               ap->ability_match = 0;
+               ap->ack_match = 0;
+
+               rx_cfg_reg = 0;
+       }
+
+       ap->rxconfig = rx_cfg_reg;
+       ret = ANEG_OK;
+
+       switch (ap->state) {
+       case ANEG_STATE_UNKNOWN:
+               if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
+                       ap->state = ANEG_STATE_AN_ENABLE;
+
+               /* fallthru */
+       case ANEG_STATE_AN_ENABLE:
+               ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
+               if (ap->flags & MR_AN_ENABLE) {
+                       ap->link_time = 0;
+                       ap->cur_time = 0;
+                       ap->ability_match_cfg = 0;
+                       ap->ability_match_count = 0;
+                       ap->ability_match = 0;
+                       ap->idle_match = 0;
+                       ap->ack_match = 0;
+
+                       ap->state = ANEG_STATE_RESTART_INIT;
+               } else {
+                       ap->state = ANEG_STATE_DISABLE_LINK_OK;
+               }
+               break;
 
        case ANEG_STATE_RESTART_INIT:
                ap->link_time = ap->cur_time;
@@ -4806,8 +5049,8 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
                                    LED_CTRL_LNKLED_OVERRIDE |
                                    LED_CTRL_1000MBPS_ON));
        } else {
-               tp->link_config.active_speed = SPEED_INVALID;
-               tp->link_config.active_duplex = DUPLEX_INVALID;
+               tp->link_config.active_speed = SPEED_UNKNOWN;
+               tp->link_config.active_duplex = DUPLEX_UNKNOWN;
                tw32(MAC_LED_CTRL, (tp->led_ctrl |
                                    LED_CTRL_LNKLED_OVERRIDE |
                                    LED_CTRL_TRAFFIC_OVERRIDE));
@@ -4855,8 +5098,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                tg3_phy_reset(tp);
 
        current_link_up = 0;
-       current_speed = SPEED_INVALID;
-       current_duplex = DUPLEX_INVALID;
+       current_speed = SPEED_UNKNOWN;
+       current_duplex = DUPLEX_UNKNOWN;
        tp->link_config.rmt_adv = 0;
 
        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -5352,7 +5595,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
                }
        }
 
-       netdev_completed_queue(tp->dev, pkts_compl, bytes_compl);
+       netdev_tx_completed_queue(txq, pkts_compl, bytes_compl);
 
        tnapi->tx_cons = sw_idx;
 
@@ -5685,6 +5928,9 @@ next_pkt_nopost:
 
        /* Refill RX ring(s). */
        if (!tg3_flag(tp, ENABLE_RSS)) {
+               /* Sync BD data before updating mailbox */
+               wmb();
+
                if (work_mask & RXD_OPAQUE_RING_STD) {
                        tpr->rx_std_prod_idx = std_prod_idx &
                                               tp->rx_std_ring_mask;
@@ -5921,6 +6167,7 @@ static inline void tg3_reset_task_cancel(struct tg3 *tp)
 {
        cancel_work_sync(&tp->reset_task);
        tg3_flag_clear(tp, RESET_TASK_PENDING);
+       tg3_flag_clear(tp, TX_RECOVERY_PENDING);
 }
 
 static int tg3_poll_msix(struct napi_struct *napi, int budget)
@@ -6292,33 +6539,6 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id)
        return IRQ_RETVAL(0);
 }
 
-static int tg3_init_hw(struct tg3 *, int);
-static int tg3_halt(struct tg3 *, int, int);
-
-/* Restart hardware after configuration changes, self-test, etc.
- * Invoked with tp->lock held.
- */
-static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
-       __releases(tp->lock)
-       __acquires(tp->lock)
-{
-       int err;
-
-       err = tg3_init_hw(tp, reset_phy);
-       if (err) {
-               netdev_err(tp->dev,
-                          "Failed to re-initialize device, aborting\n");
-               tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               tg3_full_unlock(tp);
-               del_timer_sync(&tp->timer);
-               tp->irq_sync = 0;
-               tg3_napi_enable(tp);
-               dev_close(tp->dev);
-               tg3_full_lock(tp, 0);
-       }
-       return err;
-}
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void tg3_poll_controller(struct net_device *dev)
 {
@@ -6330,50 +6550,6 @@ static void tg3_poll_controller(struct net_device *dev)
 }
 #endif
 
-static void tg3_reset_task(struct work_struct *work)
-{
-       struct tg3 *tp = container_of(work, struct tg3, reset_task);
-       int err;
-
-       tg3_full_lock(tp, 0);
-
-       if (!netif_running(tp->dev)) {
-               tg3_flag_clear(tp, RESET_TASK_PENDING);
-               tg3_full_unlock(tp);
-               return;
-       }
-
-       tg3_full_unlock(tp);
-
-       tg3_phy_stop(tp);
-
-       tg3_netif_stop(tp);
-
-       tg3_full_lock(tp, 1);
-
-       if (tg3_flag(tp, TX_RECOVERY_PENDING)) {
-               tp->write32_tx_mbox = tg3_write32_tx_mbox;
-               tp->write32_rx_mbox = tg3_write_flush_reg32;
-               tg3_flag_set(tp, MBOX_WRITE_REORDER);
-               tg3_flag_clear(tp, TX_RECOVERY_PENDING);
-       }
-
-       tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
-       err = tg3_init_hw(tp, 1);
-       if (err)
-               goto out;
-
-       tg3_netif_start(tp);
-
-out:
-       tg3_full_unlock(tp);
-
-       if (!err)
-               tg3_phy_start(tp);
-
-       tg3_flag_clear(tp, RESET_TASK_PENDING);
-}
-
 static void tg3_tx_timeout(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
@@ -6745,7 +6921,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                          ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0),
                            mss, vlan)) {
                would_hit_hwbug = 1;
-       /* Now loop through additional data fragments, and queue them. */
        } else if (skb_shinfo(skb)->nr_frags > 0) {
                u32 tmp_mss = mss;
 
@@ -6754,6 +6929,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                    !tg3_flag(tp, HW_TSO_3))
                        tmp_mss = 0;
 
+               /* Now loop through additional data
+                * fragments, and queue them.
+                */
                last = skb_shinfo(skb)->nr_frags - 1;
                for (i = 0; i <= last; i++) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -6793,7 +6971,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        skb_tx_timestamp(skb);
-       netdev_sent_queue(tp->dev, skb->len);
+       netdev_tx_sent_queue(txq, skb->len);
+
+       /* Sync BD data before updating mailbox */
+       wmb();
 
        /* Packets are ready, update Tx producer idx local and on card. */
        tw32_tx_mbox(tnapi->prodmbox, entry);
@@ -6993,66 +7174,6 @@ static int tg3_set_features(struct net_device *dev, netdev_features_t features)
        return 0;
 }
 
-static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
-                              int new_mtu)
-{
-       dev->mtu = new_mtu;
-
-       if (new_mtu > ETH_DATA_LEN) {
-               if (tg3_flag(tp, 5780_CLASS)) {
-                       netdev_update_features(dev);
-                       tg3_flag_clear(tp, TSO_CAPABLE);
-               } else {
-                       tg3_flag_set(tp, JUMBO_RING_ENABLE);
-               }
-       } else {
-               if (tg3_flag(tp, 5780_CLASS)) {
-                       tg3_flag_set(tp, TSO_CAPABLE);
-                       netdev_update_features(dev);
-               }
-               tg3_flag_clear(tp, JUMBO_RING_ENABLE);
-       }
-}
-
-static int tg3_change_mtu(struct net_device *dev, int new_mtu)
-{
-       struct tg3 *tp = netdev_priv(dev);
-       int err;
-
-       if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
-               return -EINVAL;
-
-       if (!netif_running(dev)) {
-               /* We'll just catch it later when the
-                * device is up'd.
-                */
-               tg3_set_mtu(dev, tp, new_mtu);
-               return 0;
-       }
-
-       tg3_phy_stop(tp);
-
-       tg3_netif_stop(tp);
-
-       tg3_full_lock(tp, 1);
-
-       tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-
-       tg3_set_mtu(dev, tp, new_mtu);
-
-       err = tg3_restart_hw(tp, 0);
-
-       if (!err)
-               tg3_netif_start(tp);
-
-       tg3_full_unlock(tp);
-
-       if (!err)
-               tg3_phy_start(tp);
-
-       return err;
-}
-
 static void tg3_rx_prodring_free(struct tg3 *tp,
                                 struct tg3_rx_prodring_set *tpr)
 {
@@ -7275,8 +7396,8 @@ static void tg3_free_rings(struct tg3 *tp)
 
                        dev_kfree_skb_any(skb);
                }
+               netdev_tx_reset_queue(netdev_get_tx_queue(tp->dev, j));
        }
-       netdev_reset_queue(tp->dev);
 }
 
 /* Initialize tx/rx rings for packet processing.
@@ -7886,10 +8007,8 @@ static int tg3_chip_reset(struct tg3 *tp)
        return 0;
 }
 
-static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *,
-                                                struct rtnl_link_stats64 *);
-static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *,
-                                               struct tg3_ethtool_stats *);
+static void tg3_get_nstats(struct tg3 *, struct rtnl_link_stats64 *);
+static void tg3_get_estats(struct tg3 *, struct tg3_ethtool_stats *);
 
 /* tp->lock is held. */
 static int tg3_halt(struct tg3 *tp, int kind, int silent)
@@ -7910,7 +8029,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
 
        if (tp->hw_stats) {
                /* Save the stats across chip resets... */
-               tg3_get_stats64(tp->dev, &tp->net_stats_prev),
+               tg3_get_nstats(tp, &tp->net_stats_prev);
                tg3_get_estats(tp, &tp->estats_prev);
 
                /* And make sure the next sample is new data */
@@ -7930,7 +8049,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
        int err = 0, skip_mac_1 = 0;
 
        if (!is_valid_ether_addr(addr->sa_data))
-               return -EINVAL;
+               return -EADDRNOTAVAIL;
 
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
@@ -7978,7 +8097,6 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
                              nic_addr);
 }
 
-static void __tg3_set_rx_mode(struct net_device *);
 static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 {
        int i;
@@ -8201,18 +8319,105 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
        if (tg3_flag(tp, 57765_PLUS))
                tw32(STD_REPLENISH_LWM, bdcache_maxcnt);
 
-       if (!tg3_flag(tp, JUMBO_CAPABLE) || tg3_flag(tp, 5780_CLASS))
-               return;
+       if (!tg3_flag(tp, JUMBO_CAPABLE) || tg3_flag(tp, 5780_CLASS))
+               return;
+
+       bdcache_maxcnt = TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700;
+
+       host_rep_thresh = max_t(u32, tp->rx_jumbo_pending / 8, 1);
+
+       val = min(bdcache_maxcnt / 2, host_rep_thresh);
+       tw32(RCVBDI_JUMBO_THRESH, val);
+
+       if (tg3_flag(tp, 57765_PLUS))
+               tw32(JMB_REPLENISH_LWM, bdcache_maxcnt);
+}
+
+static inline u32 calc_crc(unsigned char *buf, int len)
+{
+       u32 reg;
+       u32 tmp;
+       int j, k;
+
+       reg = 0xffffffff;
+
+       for (j = 0; j < len; j++) {
+               reg ^= buf[j];
+
+               for (k = 0; k < 8; k++) {
+                       tmp = reg & 0x01;
+
+                       reg >>= 1;
+
+                       if (tmp)
+                               reg ^= 0xedb88320;
+               }
+       }
+
+       return ~reg;
+}
+
+static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all)
+{
+       /* accept or reject all multicast frames */
+       tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
+       tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
+       tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
+       tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
+}
+
+static void __tg3_set_rx_mode(struct net_device *dev)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       u32 rx_mode;
+
+       rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
+                                 RX_MODE_KEEP_VLAN_TAG);
+
+#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE)
+       /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
+        * flag clear.
+        */
+       if (!tg3_flag(tp, ENABLE_ASF))
+               rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+#endif
 
-       bdcache_maxcnt = TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700;
+       if (dev->flags & IFF_PROMISC) {
+               /* Promiscuous mode. */
+               rx_mode |= RX_MODE_PROMISC;
+       } else if (dev->flags & IFF_ALLMULTI) {
+               /* Accept all multicast. */
+               tg3_set_multi(tp, 1);
+       } else if (netdev_mc_empty(dev)) {
+               /* Reject all multicast. */
+               tg3_set_multi(tp, 0);
+       } else {
+               /* Accept one or more multicast(s). */
+               struct netdev_hw_addr *ha;
+               u32 mc_filter[4] = { 0, };
+               u32 regidx;
+               u32 bit;
+               u32 crc;
 
-       host_rep_thresh = max_t(u32, tp->rx_jumbo_pending / 8, 1);
+               netdev_for_each_mc_addr(ha, dev) {
+                       crc = calc_crc(ha->addr, ETH_ALEN);
+                       bit = ~crc & 0x7f;
+                       regidx = (bit & 0x60) >> 5;
+                       bit &= 0x1f;
+                       mc_filter[regidx] |= (1 << bit);
+               }
 
-       val = min(bdcache_maxcnt / 2, host_rep_thresh);
-       tw32(RCVBDI_JUMBO_THRESH, val);
+               tw32(MAC_HASH_REG_0, mc_filter[0]);
+               tw32(MAC_HASH_REG_1, mc_filter[1]);
+               tw32(MAC_HASH_REG_2, mc_filter[2]);
+               tw32(MAC_HASH_REG_3, mc_filter[3]);
+       }
 
-       if (tg3_flag(tp, 57765_PLUS))
-               tw32(JMB_REPLENISH_LWM, bdcache_maxcnt);
+       if (rx_mode != tp->rx_mode) {
+               tp->rx_mode = rx_mode;
+               tw32_f(MAC_RX_MODE, rx_mode);
+               udelay(10);
+       }
 }
 
 static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp)
@@ -8690,9 +8895,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        if (tg3_flag(tp, PCI_EXPRESS))
                rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
-               rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR;
-
        if (tg3_flag(tp, HW_TSO_1) ||
            tg3_flag(tp, HW_TSO_2) ||
            tg3_flag(tp, HW_TSO_3))
@@ -9039,12 +9241,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        }
 
        if (!tg3_flag(tp, USE_PHYLIB)) {
-               if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+               if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
                        tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
-                       tp->link_config.speed = tp->link_config.orig_speed;
-                       tp->link_config.duplex = tp->link_config.orig_duplex;
-                       tp->link_config.autoneg = tp->link_config.orig_autoneg;
-               }
 
                err = tg3_setup_phy(tp, 0);
                if (err)
@@ -9347,6 +9545,108 @@ restart_timer:
        add_timer(&tp->timer);
 }
 
+static void __devinit tg3_timer_init(struct tg3 *tp)
+{
+       if (tg3_flag(tp, TAGGED_STATUS) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+           !tg3_flag(tp, 57765_CLASS))
+               tp->timer_offset = HZ;
+       else
+               tp->timer_offset = HZ / 10;
+
+       BUG_ON(tp->timer_offset > HZ);
+
+       tp->timer_multiplier = (HZ / tp->timer_offset);
+       tp->asf_multiplier = (HZ / tp->timer_offset) *
+                            TG3_FW_UPDATE_FREQ_SEC;
+
+       init_timer(&tp->timer);
+       tp->timer.data = (unsigned long) tp;
+       tp->timer.function = tg3_timer;
+}
+
+static void tg3_timer_start(struct tg3 *tp)
+{
+       tp->asf_counter   = tp->asf_multiplier;
+       tp->timer_counter = tp->timer_multiplier;
+
+       tp->timer.expires = jiffies + tp->timer_offset;
+       add_timer(&tp->timer);
+}
+
+static void tg3_timer_stop(struct tg3 *tp)
+{
+       del_timer_sync(&tp->timer);
+}
+
+/* Restart hardware after configuration changes, self-test, etc.
+ * Invoked with tp->lock held.
+ */
+static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+       __releases(tp->lock)
+       __acquires(tp->lock)
+{
+       int err;
+
+       err = tg3_init_hw(tp, reset_phy);
+       if (err) {
+               netdev_err(tp->dev,
+                          "Failed to re-initialize device, aborting\n");
+               tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+               tg3_full_unlock(tp);
+               tg3_timer_stop(tp);
+               tp->irq_sync = 0;
+               tg3_napi_enable(tp);
+               dev_close(tp->dev);
+               tg3_full_lock(tp, 0);
+       }
+       return err;
+}
+
+static void tg3_reset_task(struct work_struct *work)
+{
+       struct tg3 *tp = container_of(work, struct tg3, reset_task);
+       int err;
+
+       tg3_full_lock(tp, 0);
+
+       if (!netif_running(tp->dev)) {
+               tg3_flag_clear(tp, RESET_TASK_PENDING);
+               tg3_full_unlock(tp);
+               return;
+       }
+
+       tg3_full_unlock(tp);
+
+       tg3_phy_stop(tp);
+
+       tg3_netif_stop(tp);
+
+       tg3_full_lock(tp, 1);
+
+       if (tg3_flag(tp, TX_RECOVERY_PENDING)) {
+               tp->write32_tx_mbox = tg3_write32_tx_mbox;
+               tp->write32_rx_mbox = tg3_write_flush_reg32;
+               tg3_flag_set(tp, MBOX_WRITE_REORDER);
+               tg3_flag_clear(tp, TX_RECOVERY_PENDING);
+       }
+
+       tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
+       err = tg3_init_hw(tp, 1);
+       if (err)
+               goto out;
+
+       tg3_netif_start(tp);
+
+out:
+       tg3_full_unlock(tp);
+
+       if (!err)
+               tg3_phy_start(tp);
+
+       tg3_flag_clear(tp, RESET_TASK_PENDING);
+}
+
 static int tg3_request_irq(struct tg3 *tp, int irq_num)
 {
        irq_handler_t fn;
@@ -9401,7 +9701,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
        }
 
        err = request_irq(tnapi->irq_vec, tg3_test_isr,
-                         IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
+                         IRQF_SHARED, dev->name, tnapi);
        if (err)
                return err;
 
@@ -9712,24 +10012,6 @@ static int tg3_open(struct net_device *dev)
        if (err) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
                tg3_free_rings(tp);
-       } else {
-               if (tg3_flag(tp, TAGGED_STATUS) &&
-                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
-                   !tg3_flag(tp, 57765_CLASS))
-                       tp->timer_offset = HZ;
-               else
-                       tp->timer_offset = HZ / 10;
-
-               BUG_ON(tp->timer_offset > HZ);
-               tp->timer_counter = tp->timer_multiplier =
-                       (HZ / tp->timer_offset);
-               tp->asf_counter = tp->asf_multiplier =
-                       ((HZ / tp->timer_offset) * 2);
-
-               init_timer(&tp->timer);
-               tp->timer.expires = jiffies + tp->timer_offset;
-               tp->timer.data = (unsigned long) tp;
-               tp->timer.function = tg3_timer;
        }
 
        tg3_full_unlock(tp);
@@ -9761,7 +10043,7 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_lock(tp, 0);
 
-       add_timer(&tp->timer);
+       tg3_timer_start(tp);
        tg3_flag_set(tp, INIT_COMPLETE);
        tg3_enable_ints(tp);
 
@@ -9806,7 +10088,7 @@ static int tg3_close(struct net_device *dev)
 
        netif_tx_stop_all_queues(dev);
 
-       del_timer_sync(&tp->timer);
+       tg3_timer_stop(tp);
 
        tg3_phy_stop(tp);
 
@@ -9847,7 +10129,7 @@ static inline u64 get_stat64(tg3_stat64_t *val)
        return ((u64)val->high << 32) | ((u64)val->low);
 }
 
-static u64 calc_crc_errors(struct tg3 *tp)
+static u64 tg3_calc_crc_errors(struct tg3 *tp)
 {
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
@@ -9856,14 +10138,12 @@ static u64 calc_crc_errors(struct tg3 *tp)
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
                u32 val;
 
-               spin_lock_bh(&tp->lock);
                if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) {
                        tg3_writephy(tp, MII_TG3_TEST1,
                                     val | MII_TG3_TEST1_CRC_EN);
                        tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &val);
                } else
                        val = 0;
-               spin_unlock_bh(&tp->lock);
 
                tp->phy_crc_errors += val;
 
@@ -9877,15 +10157,11 @@ static u64 calc_crc_errors(struct tg3 *tp)
        estats->member =        old_estats->member + \
                                get_stat64(&hw_stats->member)
 
-static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp,
-                                              struct tg3_ethtool_stats *estats)
+static void tg3_get_estats(struct tg3 *tp, struct tg3_ethtool_stats *estats)
 {
        struct tg3_ethtool_stats *old_estats = &tp->estats_prev;
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
-       if (!hw_stats)
-               return old_estats;
-
        ESTAT_ADD(rx_octets);
        ESTAT_ADD(rx_fragments);
        ESTAT_ADD(rx_ucast_packets);
@@ -9963,20 +10239,13 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp,
        ESTAT_ADD(nic_tx_threshold_hit);
 
        ESTAT_ADD(mbuf_lwm_thresh_hit);
-
-       return estats;
 }
 
-static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
-                                                struct rtnl_link_stats64 *stats)
+static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats)
 {
-       struct tg3 *tp = netdev_priv(dev);
        struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev;
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
-       if (!hw_stats)
-               return old_stats;
-
        stats->rx_packets = old_stats->rx_packets +
                get_stat64(&hw_stats->rx_ucast_packets) +
                get_stat64(&hw_stats->rx_mcast_packets) +
@@ -10009,124 +10278,23 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
                get_stat64(&hw_stats->rx_frame_too_long_errors) +
                get_stat64(&hw_stats->rx_undersize_packets);
 
-       stats->rx_over_errors = old_stats->rx_over_errors +
-               get_stat64(&hw_stats->rxbds_empty);
-       stats->rx_frame_errors = old_stats->rx_frame_errors +
-               get_stat64(&hw_stats->rx_align_errors);
-       stats->tx_aborted_errors = old_stats->tx_aborted_errors +
-               get_stat64(&hw_stats->tx_discards);
-       stats->tx_carrier_errors = old_stats->tx_carrier_errors +
-               get_stat64(&hw_stats->tx_carrier_sense_errors);
-
-       stats->rx_crc_errors = old_stats->rx_crc_errors +
-               calc_crc_errors(tp);
-
-       stats->rx_missed_errors = old_stats->rx_missed_errors +
-               get_stat64(&hw_stats->rx_discards);
-
-       stats->rx_dropped = tp->rx_dropped;
-       stats->tx_dropped = tp->tx_dropped;
-
-       return stats;
-}
-
-static inline u32 calc_crc(unsigned char *buf, int len)
-{
-       u32 reg;
-       u32 tmp;
-       int j, k;
-
-       reg = 0xffffffff;
-
-       for (j = 0; j < len; j++) {
-               reg ^= buf[j];
-
-               for (k = 0; k < 8; k++) {
-                       tmp = reg & 0x01;
-
-                       reg >>= 1;
-
-                       if (tmp)
-                               reg ^= 0xedb88320;
-               }
-       }
-
-       return ~reg;
-}
-
-static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all)
-{
-       /* accept or reject all multicast frames */
-       tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
-       tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
-       tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
-       tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
-}
-
-static void __tg3_set_rx_mode(struct net_device *dev)
-{
-       struct tg3 *tp = netdev_priv(dev);
-       u32 rx_mode;
-
-       rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
-                                 RX_MODE_KEEP_VLAN_TAG);
-
-#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE)
-       /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
-        * flag clear.
-        */
-       if (!tg3_flag(tp, ENABLE_ASF))
-               rx_mode |= RX_MODE_KEEP_VLAN_TAG;
-#endif
-
-       if (dev->flags & IFF_PROMISC) {
-               /* Promiscuous mode. */
-               rx_mode |= RX_MODE_PROMISC;
-       } else if (dev->flags & IFF_ALLMULTI) {
-               /* Accept all multicast. */
-               tg3_set_multi(tp, 1);
-       } else if (netdev_mc_empty(dev)) {
-               /* Reject all multicast. */
-               tg3_set_multi(tp, 0);
-       } else {
-               /* Accept one or more multicast(s). */
-               struct netdev_hw_addr *ha;
-               u32 mc_filter[4] = { 0, };
-               u32 regidx;
-               u32 bit;
-               u32 crc;
-
-               netdev_for_each_mc_addr(ha, dev) {
-                       crc = calc_crc(ha->addr, ETH_ALEN);
-                       bit = ~crc & 0x7f;
-                       regidx = (bit & 0x60) >> 5;
-                       bit &= 0x1f;
-                       mc_filter[regidx] |= (1 << bit);
-               }
-
-               tw32(MAC_HASH_REG_0, mc_filter[0]);
-               tw32(MAC_HASH_REG_1, mc_filter[1]);
-               tw32(MAC_HASH_REG_2, mc_filter[2]);
-               tw32(MAC_HASH_REG_3, mc_filter[3]);
-       }
-
-       if (rx_mode != tp->rx_mode) {
-               tp->rx_mode = rx_mode;
-               tw32_f(MAC_RX_MODE, rx_mode);
-               udelay(10);
-       }
-}
-
-static void tg3_set_rx_mode(struct net_device *dev)
-{
-       struct tg3 *tp = netdev_priv(dev);
+       stats->rx_over_errors = old_stats->rx_over_errors +
+               get_stat64(&hw_stats->rxbds_empty);
+       stats->rx_frame_errors = old_stats->rx_frame_errors +
+               get_stat64(&hw_stats->rx_align_errors);
+       stats->tx_aborted_errors = old_stats->tx_aborted_errors +
+               get_stat64(&hw_stats->tx_discards);
+       stats->tx_carrier_errors = old_stats->tx_carrier_errors +
+               get_stat64(&hw_stats->tx_carrier_sense_errors);
 
-       if (!netif_running(dev))
-               return;
+       stats->rx_crc_errors = old_stats->rx_crc_errors +
+               tg3_calc_crc_errors(tp);
 
-       tg3_full_lock(tp, 0);
-       __tg3_set_rx_mode(dev);
-       tg3_full_unlock(tp);
+       stats->rx_missed_errors = old_stats->rx_missed_errors +
+               get_stat64(&hw_stats->rx_discards);
+
+       stats->rx_dropped = tp->rx_dropped;
+       stats->tx_dropped = tp->tx_dropped;
 }
 
 static int tg3_get_regs_len(struct net_device *dev)
@@ -10223,8 +10391,6 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        return 0;
 }
 
-static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf);
-
 static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
 {
        struct tg3 *tp = netdev_priv(dev);
@@ -10338,8 +10504,8 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                cmd->eth_tp_mdix = ETH_TP_MDI;
                }
        } else {
-               ethtool_cmd_speed_set(cmd, SPEED_INVALID);
-               cmd->duplex = DUPLEX_INVALID;
+               ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+               cmd->duplex = DUPLEX_UNKNOWN;
                cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
        }
        cmd->phy_address = tp->phy_addr;
@@ -10421,18 +10587,14 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (cmd->autoneg == AUTONEG_ENABLE) {
                tp->link_config.advertising = (cmd->advertising |
                                              ADVERTISED_Autoneg);
-               tp->link_config.speed = SPEED_INVALID;
-               tp->link_config.duplex = DUPLEX_INVALID;
+               tp->link_config.speed = SPEED_UNKNOWN;
+               tp->link_config.duplex = DUPLEX_UNKNOWN;
        } else {
                tp->link_config.advertising = 0;
                tp->link_config.speed = speed;
                tp->link_config.duplex = cmd->duplex;
        }
 
-       tp->link_config.orig_speed = tp->link_config.speed;
-       tp->link_config.orig_duplex = tp->link_config.duplex;
-       tp->link_config.orig_autoneg = tp->link_config.autoneg;
-
        if (netif_running(dev))
                tg3_setup_phy(tp, 1);
 
@@ -10679,10 +10841,10 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
                        if (!epause->autoneg)
                                tg3_setup_flow_control(tp, 0, 0);
                } else {
-                       tp->link_config.orig_advertising &=
+                       tp->link_config.advertising &=
                                        ~(ADVERTISED_Pause |
                                          ADVERTISED_Asym_Pause);
-                       tp->link_config.orig_advertising |= newadv;
+                       tp->link_config.advertising |= newadv;
                }
        } else {
                int irq_sync = 0;
@@ -10859,7 +11021,10 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats);
+       if (tp->hw_stats)
+               tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats);
+       else
+               memset(tmp_stats, 0, sizeof(struct tg3_ethtool_stats));
 }
 
 static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
@@ -11568,6 +11733,10 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback)
        } else {
                num_pkts = 1;
                data_off = ETH_HLEN;
+
+               if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
+                   tx_len > VLAN_ETH_FRAME_LEN)
+                       base_flags |= TXD_FLAG_JMB_PKT;
        }
 
        for (i = data_off; i < tx_len; i++)
@@ -11600,6 +11769,9 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback)
 
        tnapi->tx_prod++;
 
+       /* Sync BD data before updating mailbox */
+       wmb();
+
        tw32_tx_mbox(tnapi->prodmbox, tnapi->tx_prod);
        tr32_mailbox(tnapi->prodmbox);
 
@@ -11698,6 +11870,10 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 {
        int err = -EIO;
        u32 eee_cap;
+       u32 jmb_pkt_sz = 9000;
+
+       if (tp->dma_limit)
+               jmb_pkt_sz = tp->dma_limit - ETH_HLEN;
 
        eee_cap = tp->phy_flags & TG3_PHYFLG_EEE_CAP;
        tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
@@ -11741,7 +11917,7 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                        data[0] |= TG3_STD_LOOPBACK_FAILED;
 
                if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
-                   tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+                   tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
                        data[0] |= TG3_JMB_LOOPBACK_FAILED;
 
                tg3_mac_loopback(tp, false);
@@ -11766,7 +11942,7 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                    tg3_run_loopback(tp, ETH_FRAME_LEN, true))
                        data[1] |= TG3_TSO_LOOPBACK_FAILED;
                if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
-                   tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+                   tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
                        data[1] |= TG3_JMB_LOOPBACK_FAILED;
 
                if (do_extlpbk) {
@@ -11784,7 +11960,7 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                            tg3_run_loopback(tp, ETH_FRAME_LEN, true))
                                data[2] |= TG3_TSO_LOOPBACK_FAILED;
                        if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
-                           tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+                           tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
                                data[2] |= TG3_JMB_LOOPBACK_FAILED;
                }
 
@@ -11989,994 +12165,857 @@ static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
            (ec->tx_max_coalesced_frames == 0))
                return -EINVAL;
 
-       /* Only copy relevant parameters, ignore all others. */
-       tp->coal.rx_coalesce_usecs = ec->rx_coalesce_usecs;
-       tp->coal.tx_coalesce_usecs = ec->tx_coalesce_usecs;
-       tp->coal.rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
-       tp->coal.tx_max_coalesced_frames = ec->tx_max_coalesced_frames;
-       tp->coal.rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq;
-       tp->coal.tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq;
-       tp->coal.rx_max_coalesced_frames_irq = ec->rx_max_coalesced_frames_irq;
-       tp->coal.tx_max_coalesced_frames_irq = ec->tx_max_coalesced_frames_irq;
-       tp->coal.stats_block_coalesce_usecs = ec->stats_block_coalesce_usecs;
-
-       if (netif_running(dev)) {
-               tg3_full_lock(tp, 0);
-               __tg3_set_coalesce(tp, &tp->coal);
-               tg3_full_unlock(tp);
-       }
-       return 0;
-}
-
-static const struct ethtool_ops tg3_ethtool_ops = {
-       .get_settings           = tg3_get_settings,
-       .set_settings           = tg3_set_settings,
-       .get_drvinfo            = tg3_get_drvinfo,
-       .get_regs_len           = tg3_get_regs_len,
-       .get_regs               = tg3_get_regs,
-       .get_wol                = tg3_get_wol,
-       .set_wol                = tg3_set_wol,
-       .get_msglevel           = tg3_get_msglevel,
-       .set_msglevel           = tg3_set_msglevel,
-       .nway_reset             = tg3_nway_reset,
-       .get_link               = ethtool_op_get_link,
-       .get_eeprom_len         = tg3_get_eeprom_len,
-       .get_eeprom             = tg3_get_eeprom,
-       .set_eeprom             = tg3_set_eeprom,
-       .get_ringparam          = tg3_get_ringparam,
-       .set_ringparam          = tg3_set_ringparam,
-       .get_pauseparam         = tg3_get_pauseparam,
-       .set_pauseparam         = tg3_set_pauseparam,
-       .self_test              = tg3_self_test,
-       .get_strings            = tg3_get_strings,
-       .set_phys_id            = tg3_set_phys_id,
-       .get_ethtool_stats      = tg3_get_ethtool_stats,
-       .get_coalesce           = tg3_get_coalesce,
-       .set_coalesce           = tg3_set_coalesce,
-       .get_sset_count         = tg3_get_sset_count,
-       .get_rxnfc              = tg3_get_rxnfc,
-       .get_rxfh_indir_size    = tg3_get_rxfh_indir_size,
-       .get_rxfh_indir         = tg3_get_rxfh_indir,
-       .set_rxfh_indir         = tg3_set_rxfh_indir,
-};
-
-static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
-{
-       u32 cursize, val, magic;
-
-       tp->nvram_size = EEPROM_CHIP_SIZE;
-
-       if (tg3_nvram_read(tp, 0, &magic) != 0)
-               return;
-
-       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;
-
-       /*
-        * Size the chip by reading offsets at increasing powers of two.
-        * When we encounter our validation signature, we know the addressing
-        * has wrapped around, and thus have our chip size.
-        */
-       cursize = 0x10;
-
-       while (cursize < tp->nvram_size) {
-               if (tg3_nvram_read(tp, cursize, &val) != 0)
-                       return;
-
-               if (val == magic)
-                       break;
-
-               cursize <<= 1;
-       }
-
-       tp->nvram_size = cursize;
-}
-
-static void __devinit tg3_get_nvram_size(struct tg3 *tp)
-{
-       u32 val;
-
-       if (tg3_flag(tp, NO_NVRAM) || tg3_nvram_read(tp, 0, &val) != 0)
-               return;
-
-       /* Selfboot format */
-       if (val != TG3_EEPROM_MAGIC) {
-               tg3_get_eeprom_size(tp);
-               return;
-       }
-
-       if (tg3_nvram_read(tp, 0xf0, &val) == 0) {
-               if (val != 0) {
-                       /* This is confusing.  We want to operate on the
-                        * 16-bit value at offset 0xf2.  The tg3_nvram_read()
-                        * call will read from NVRAM and byteswap the data
-                        * according to the byteswapping settings for all
-                        * other register accesses.  This ensures the data we
-                        * want will always reside in the lower 16-bits.
-                        * However, the data in NVRAM is in LE format, which
-                        * means the data from the NVRAM read will always be
-                        * opposite the endianness of the CPU.  The 16-bit
-                        * byteswap then brings the data to CPU endianness.
-                        */
-                       tp->nvram_size = swab16((u16)(val & 0x0000ffff)) * 1024;
-                       return;
-               }
-       }
-       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
-}
-
-static void __devinit tg3_get_nvram_info(struct tg3 *tp)
-{
-       u32 nvcfg1;
-
-       nvcfg1 = tr32(NVRAM_CFG1);
-       if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
-               tg3_flag_set(tp, FLASH);
-       } else {
-               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-               tw32(NVRAM_CFG1, nvcfg1);
-       }
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
-           tg3_flag(tp, 5780_CLASS)) {
-               switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
-               case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
-                       tp->nvram_jedecnum = JEDEC_ATMEL;
-                       tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
-                       tg3_flag_set(tp, NVRAM_BUFFERED);
-                       break;
-               case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED:
-                       tp->nvram_jedecnum = JEDEC_ATMEL;
-                       tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE;
-                       break;
-               case FLASH_VENDOR_ATMEL_EEPROM:
-                       tp->nvram_jedecnum = JEDEC_ATMEL;
-                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-                       tg3_flag_set(tp, NVRAM_BUFFERED);
-                       break;
-               case FLASH_VENDOR_ST:
-                       tp->nvram_jedecnum = JEDEC_ST;
-                       tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE;
-                       tg3_flag_set(tp, NVRAM_BUFFERED);
-                       break;
-               case FLASH_VENDOR_SAIFUN:
-                       tp->nvram_jedecnum = JEDEC_SAIFUN;
-                       tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE;
-                       break;
-               case FLASH_VENDOR_SST_SMALL:
-               case FLASH_VENDOR_SST_LARGE:
-                       tp->nvram_jedecnum = JEDEC_SST;
-                       tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE;
-                       break;
-               }
-       } else {
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-       }
-}
-
-static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
-{
-       switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
-       case FLASH_5752PAGE_SIZE_256:
-               tp->nvram_pagesize = 256;
-               break;
-       case FLASH_5752PAGE_SIZE_512:
-               tp->nvram_pagesize = 512;
-               break;
-       case FLASH_5752PAGE_SIZE_1K:
-               tp->nvram_pagesize = 1024;
-               break;
-       case FLASH_5752PAGE_SIZE_2K:
-               tp->nvram_pagesize = 2048;
-               break;
-       case FLASH_5752PAGE_SIZE_4K:
-               tp->nvram_pagesize = 4096;
-               break;
-       case FLASH_5752PAGE_SIZE_264:
-               tp->nvram_pagesize = 264;
-               break;
-       case FLASH_5752PAGE_SIZE_528:
-               tp->nvram_pagesize = 528;
-               break;
-       }
-}
-
-static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
-{
-       u32 nvcfg1;
-
-       nvcfg1 = tr32(NVRAM_CFG1);
-
-       /* NVRAM protection for TPM */
-       if (nvcfg1 & (1 << 27))
-               tg3_flag_set(tp, PROTECTED_NVRAM);
-
-       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-       case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ:
-       case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               break;
-       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               break;
-       case FLASH_5752VENDOR_ST_M45PE10:
-       case FLASH_5752VENDOR_ST_M45PE20:
-       case FLASH_5752VENDOR_ST_M45PE40:
-               tp->nvram_jedecnum = JEDEC_ST;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               break;
-       }
-
-       if (tg3_flag(tp, FLASH)) {
-               tg3_nvram_get_pagesize(tp, nvcfg1);
-       } else {
-               /* For eeprom, set pagesize to maximum eeprom size */
-               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+       /* Only copy relevant parameters, ignore all others. */
+       tp->coal.rx_coalesce_usecs = ec->rx_coalesce_usecs;
+       tp->coal.tx_coalesce_usecs = ec->tx_coalesce_usecs;
+       tp->coal.rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
+       tp->coal.tx_max_coalesced_frames = ec->tx_max_coalesced_frames;
+       tp->coal.rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq;
+       tp->coal.tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq;
+       tp->coal.rx_max_coalesced_frames_irq = ec->rx_max_coalesced_frames_irq;
+       tp->coal.tx_max_coalesced_frames_irq = ec->tx_max_coalesced_frames_irq;
+       tp->coal.stats_block_coalesce_usecs = ec->stats_block_coalesce_usecs;
 
-               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-               tw32(NVRAM_CFG1, nvcfg1);
+       if (netif_running(dev)) {
+               tg3_full_lock(tp, 0);
+               __tg3_set_coalesce(tp, &tp->coal);
+               tg3_full_unlock(tp);
        }
+       return 0;
 }
 
-static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+static const struct ethtool_ops tg3_ethtool_ops = {
+       .get_settings           = tg3_get_settings,
+       .set_settings           = tg3_set_settings,
+       .get_drvinfo            = tg3_get_drvinfo,
+       .get_regs_len           = tg3_get_regs_len,
+       .get_regs               = tg3_get_regs,
+       .get_wol                = tg3_get_wol,
+       .set_wol                = tg3_set_wol,
+       .get_msglevel           = tg3_get_msglevel,
+       .set_msglevel           = tg3_set_msglevel,
+       .nway_reset             = tg3_nway_reset,
+       .get_link               = ethtool_op_get_link,
+       .get_eeprom_len         = tg3_get_eeprom_len,
+       .get_eeprom             = tg3_get_eeprom,
+       .set_eeprom             = tg3_set_eeprom,
+       .get_ringparam          = tg3_get_ringparam,
+       .set_ringparam          = tg3_set_ringparam,
+       .get_pauseparam         = tg3_get_pauseparam,
+       .set_pauseparam         = tg3_set_pauseparam,
+       .self_test              = tg3_self_test,
+       .get_strings            = tg3_get_strings,
+       .set_phys_id            = tg3_set_phys_id,
+       .get_ethtool_stats      = tg3_get_ethtool_stats,
+       .get_coalesce           = tg3_get_coalesce,
+       .set_coalesce           = tg3_set_coalesce,
+       .get_sset_count         = tg3_get_sset_count,
+       .get_rxnfc              = tg3_get_rxnfc,
+       .get_rxfh_indir_size    = tg3_get_rxfh_indir_size,
+       .get_rxfh_indir         = tg3_get_rxfh_indir,
+       .set_rxfh_indir         = tg3_set_rxfh_indir,
+};
+
+static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
+                                               struct rtnl_link_stats64 *stats)
 {
-       u32 nvcfg1, protect = 0;
+       struct tg3 *tp = netdev_priv(dev);
 
-       nvcfg1 = tr32(NVRAM_CFG1);
+       if (!tp->hw_stats)
+               return &tp->net_stats_prev;
 
-       /* NVRAM protection for TPM */
-       if (nvcfg1 & (1 << 27)) {
-               tg3_flag_set(tp, PROTECTED_NVRAM);
-               protect = 1;
-       }
+       spin_lock_bh(&tp->lock);
+       tg3_get_nstats(tp, stats);
+       spin_unlock_bh(&tp->lock);
 
-       nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
-       switch (nvcfg1) {
-       case FLASH_5755VENDOR_ATMEL_FLASH_1:
-       case FLASH_5755VENDOR_ATMEL_FLASH_2:
-       case FLASH_5755VENDOR_ATMEL_FLASH_3:
-       case FLASH_5755VENDOR_ATMEL_FLASH_5:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               tp->nvram_pagesize = 264;
-               if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
-                   nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
-                       tp->nvram_size = (protect ? 0x3e200 :
-                                         TG3_NVRAM_SIZE_512KB);
-               else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
-                       tp->nvram_size = (protect ? 0x1f200 :
-                                         TG3_NVRAM_SIZE_256KB);
-               else
-                       tp->nvram_size = (protect ? 0x1f200 :
-                                         TG3_NVRAM_SIZE_128KB);
-               break;
-       case FLASH_5752VENDOR_ST_M45PE10:
-       case FLASH_5752VENDOR_ST_M45PE20:
-       case FLASH_5752VENDOR_ST_M45PE40:
-               tp->nvram_jedecnum = JEDEC_ST;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               tp->nvram_pagesize = 256;
-               if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
-                       tp->nvram_size = (protect ?
-                                         TG3_NVRAM_SIZE_64KB :
-                                         TG3_NVRAM_SIZE_128KB);
-               else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
-                       tp->nvram_size = (protect ?
-                                         TG3_NVRAM_SIZE_64KB :
-                                         TG3_NVRAM_SIZE_256KB);
-               else
-                       tp->nvram_size = (protect ?
-                                         TG3_NVRAM_SIZE_128KB :
-                                         TG3_NVRAM_SIZE_512KB);
-               break;
-       }
+       return stats;
 }
 
-static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+static void tg3_set_rx_mode(struct net_device *dev)
 {
-       u32 nvcfg1;
+       struct tg3 *tp = netdev_priv(dev);
 
-       nvcfg1 = tr32(NVRAM_CFG1);
+       if (!netif_running(dev))
+               return;
 
-       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-       case FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ:
-       case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
-       case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ:
-       case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+       tg3_full_lock(tp, 0);
+       __tg3_set_rx_mode(dev);
+       tg3_full_unlock(tp);
+}
 
-               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-               tw32(NVRAM_CFG1, nvcfg1);
-               break;
-       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
-       case FLASH_5755VENDOR_ATMEL_FLASH_1:
-       case FLASH_5755VENDOR_ATMEL_FLASH_2:
-       case FLASH_5755VENDOR_ATMEL_FLASH_3:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               tp->nvram_pagesize = 264;
-               break;
-       case FLASH_5752VENDOR_ST_M45PE10:
-       case FLASH_5752VENDOR_ST_M45PE20:
-       case FLASH_5752VENDOR_ST_M45PE40:
-               tp->nvram_jedecnum = JEDEC_ST;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               tp->nvram_pagesize = 256;
-               break;
+static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
+                              int new_mtu)
+{
+       dev->mtu = new_mtu;
+
+       if (new_mtu > ETH_DATA_LEN) {
+               if (tg3_flag(tp, 5780_CLASS)) {
+                       netdev_update_features(dev);
+                       tg3_flag_clear(tp, TSO_CAPABLE);
+               } else {
+                       tg3_flag_set(tp, JUMBO_RING_ENABLE);
+               }
+       } else {
+               if (tg3_flag(tp, 5780_CLASS)) {
+                       tg3_flag_set(tp, TSO_CAPABLE);
+                       netdev_update_features(dev);
+               }
+               tg3_flag_clear(tp, JUMBO_RING_ENABLE);
        }
 }
 
-static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 {
-       u32 nvcfg1, protect = 0;
+       struct tg3 *tp = netdev_priv(dev);
+       int err, reset_phy = 0;
 
-       nvcfg1 = tr32(NVRAM_CFG1);
+       if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
+               return -EINVAL;
 
-       /* NVRAM protection for TPM */
-       if (nvcfg1 & (1 << 27)) {
-               tg3_flag_set(tp, PROTECTED_NVRAM);
-               protect = 1;
+       if (!netif_running(dev)) {
+               /* We'll just catch it later when the
+                * device is up'd.
+                */
+               tg3_set_mtu(dev, tp, new_mtu);
+               return 0;
        }
 
-       nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
-       switch (nvcfg1) {
-       case FLASH_5761VENDOR_ATMEL_ADB021D:
-       case FLASH_5761VENDOR_ATMEL_ADB041D:
-       case FLASH_5761VENDOR_ATMEL_ADB081D:
-       case FLASH_5761VENDOR_ATMEL_ADB161D:
-       case FLASH_5761VENDOR_ATMEL_MDB021D:
-       case FLASH_5761VENDOR_ATMEL_MDB041D:
-       case FLASH_5761VENDOR_ATMEL_MDB081D:
-       case FLASH_5761VENDOR_ATMEL_MDB161D:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
-               tp->nvram_pagesize = 256;
-               break;
-       case FLASH_5761VENDOR_ST_A_M45PE20:
-       case FLASH_5761VENDOR_ST_A_M45PE40:
-       case FLASH_5761VENDOR_ST_A_M45PE80:
-       case FLASH_5761VENDOR_ST_A_M45PE16:
-       case FLASH_5761VENDOR_ST_M_M45PE20:
-       case FLASH_5761VENDOR_ST_M_M45PE40:
-       case FLASH_5761VENDOR_ST_M_M45PE80:
-       case FLASH_5761VENDOR_ST_M_M45PE16:
-               tp->nvram_jedecnum = JEDEC_ST;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-               tp->nvram_pagesize = 256;
-               break;
-       }
+       tg3_phy_stop(tp);
 
-       if (protect) {
-               tp->nvram_size = tr32(NVRAM_ADDR_LOCKOUT);
-       } else {
-               switch (nvcfg1) {
-               case FLASH_5761VENDOR_ATMEL_ADB161D:
-               case FLASH_5761VENDOR_ATMEL_MDB161D:
-               case FLASH_5761VENDOR_ST_A_M45PE16:
-               case FLASH_5761VENDOR_ST_M_M45PE16:
-                       tp->nvram_size = TG3_NVRAM_SIZE_2MB;
-                       break;
-               case FLASH_5761VENDOR_ATMEL_ADB081D:
-               case FLASH_5761VENDOR_ATMEL_MDB081D:
-               case FLASH_5761VENDOR_ST_A_M45PE80:
-               case FLASH_5761VENDOR_ST_M_M45PE80:
-                       tp->nvram_size = TG3_NVRAM_SIZE_1MB;
-                       break;
-               case FLASH_5761VENDOR_ATMEL_ADB041D:
-               case FLASH_5761VENDOR_ATMEL_MDB041D:
-               case FLASH_5761VENDOR_ST_A_M45PE40:
-               case FLASH_5761VENDOR_ST_M_M45PE40:
-                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
-                       break;
-               case FLASH_5761VENDOR_ATMEL_ADB021D:
-               case FLASH_5761VENDOR_ATMEL_MDB021D:
-               case FLASH_5761VENDOR_ST_A_M45PE20:
-               case FLASH_5761VENDOR_ST_M_M45PE20:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
-                       break;
-               }
-       }
-}
+       tg3_netif_stop(tp);
+
+       tg3_full_lock(tp, 1);
+
+       tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+
+       tg3_set_mtu(dev, tp, new_mtu);
+
+       /* Reset PHY, otherwise the read DMA engine will be in a mode that
+        * breaks all requests to 256 bytes.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
+               reset_phy = 1;
 
-static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
-{
-       tp->nvram_jedecnum = JEDEC_ATMEL;
-       tg3_flag_set(tp, NVRAM_BUFFERED);
-       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+       err = tg3_restart_hw(tp, reset_phy);
+
+       if (!err)
+               tg3_netif_start(tp);
+
+       tg3_full_unlock(tp);
+
+       if (!err)
+               tg3_phy_start(tp);
+
+       return err;
 }
 
-static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+static const struct net_device_ops tg3_netdev_ops = {
+       .ndo_open               = tg3_open,
+       .ndo_stop               = tg3_close,
+       .ndo_start_xmit         = tg3_start_xmit,
+       .ndo_get_stats64        = tg3_get_stats64,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_rx_mode        = tg3_set_rx_mode,
+       .ndo_set_mac_address    = tg3_set_mac_addr,
+       .ndo_do_ioctl           = tg3_ioctl,
+       .ndo_tx_timeout         = tg3_tx_timeout,
+       .ndo_change_mtu         = tg3_change_mtu,
+       .ndo_fix_features       = tg3_fix_features,
+       .ndo_set_features       = tg3_set_features,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = tg3_poll_controller,
+#endif
+};
+
+static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
 {
-       u32 nvcfg1;
+       u32 cursize, val, magic;
 
-       nvcfg1 = tr32(NVRAM_CFG1);
+       tp->nvram_size = EEPROM_CHIP_SIZE;
 
-       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-       case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
-       case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+       if (tg3_nvram_read(tp, 0, &magic) != 0)
+               return;
 
-               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-               tw32(NVRAM_CFG1, nvcfg1);
+       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;
-       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
-       case FLASH_57780VENDOR_ATMEL_AT45DB011D:
-       case FLASH_57780VENDOR_ATMEL_AT45DB011B:
-       case FLASH_57780VENDOR_ATMEL_AT45DB021D:
-       case FLASH_57780VENDOR_ATMEL_AT45DB021B:
-       case FLASH_57780VENDOR_ATMEL_AT45DB041D:
-       case FLASH_57780VENDOR_ATMEL_AT45DB041B:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
 
-               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-               case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
-               case FLASH_57780VENDOR_ATMEL_AT45DB011D:
-               case FLASH_57780VENDOR_ATMEL_AT45DB011B:
-                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
-                       break;
-               case FLASH_57780VENDOR_ATMEL_AT45DB021D:
-               case FLASH_57780VENDOR_ATMEL_AT45DB021B:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
-                       break;
-               case FLASH_57780VENDOR_ATMEL_AT45DB041D:
-               case FLASH_57780VENDOR_ATMEL_AT45DB041B:
-                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
-                       break;
-               }
-               break;
-       case FLASH_5752VENDOR_ST_M45PE10:
-       case FLASH_5752VENDOR_ST_M45PE20:
-       case FLASH_5752VENDOR_ST_M45PE40:
-               tp->nvram_jedecnum = JEDEC_ST;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
+       /*
+        * Size the chip by reading offsets at increasing powers of two.
+        * When we encounter our validation signature, we know the addressing
+        * has wrapped around, and thus have our chip size.
+        */
+       cursize = 0x10;
 
-               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-               case FLASH_5752VENDOR_ST_M45PE10:
-                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
-                       break;
-               case FLASH_5752VENDOR_ST_M45PE20:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
-                       break;
-               case FLASH_5752VENDOR_ST_M45PE40:
-                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+       while (cursize < tp->nvram_size) {
+               if (tg3_nvram_read(tp, cursize, &val) != 0)
+                       return;
+
+               if (val == magic)
                        break;
-               }
-               break;
-       default:
-               tg3_flag_set(tp, NO_NVRAM);
-               return;
+
+               cursize <<= 1;
        }
 
-       tg3_nvram_get_pagesize(tp, nvcfg1);
-       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
-               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
+       tp->nvram_size = cursize;
 }
 
+static void __devinit tg3_get_nvram_size(struct tg3 *tp)
+{
+       u32 val;
 
-static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+       if (tg3_flag(tp, NO_NVRAM) || tg3_nvram_read(tp, 0, &val) != 0)
+               return;
+
+       /* Selfboot format */
+       if (val != TG3_EEPROM_MAGIC) {
+               tg3_get_eeprom_size(tp);
+               return;
+       }
+
+       if (tg3_nvram_read(tp, 0xf0, &val) == 0) {
+               if (val != 0) {
+                       /* This is confusing.  We want to operate on the
+                        * 16-bit value at offset 0xf2.  The tg3_nvram_read()
+                        * call will read from NVRAM and byteswap the data
+                        * according to the byteswapping settings for all
+                        * other register accesses.  This ensures the data we
+                        * want will always reside in the lower 16-bits.
+                        * However, the data in NVRAM is in LE format, which
+                        * means the data from the NVRAM read will always be
+                        * opposite the endianness of the CPU.  The 16-bit
+                        * byteswap then brings the data to CPU endianness.
+                        */
+                       tp->nvram_size = swab16((u16)(val & 0x0000ffff)) * 1024;
+                       return;
+               }
+       }
+       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+}
+
+static void __devinit tg3_get_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
        nvcfg1 = tr32(NVRAM_CFG1);
-
-       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-       case FLASH_5717VENDOR_ATMEL_EEPROM:
-       case FLASH_5717VENDOR_MICRO_EEPROM:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-
+       if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
+               tg3_flag_set(tp, FLASH);
+       } else {
                nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
                tw32(NVRAM_CFG1, nvcfg1);
-               return;
-       case FLASH_5717VENDOR_ATMEL_MDB011D:
-       case FLASH_5717VENDOR_ATMEL_ADB011B:
-       case FLASH_5717VENDOR_ATMEL_ADB011D:
-       case FLASH_5717VENDOR_ATMEL_MDB021D:
-       case FLASH_5717VENDOR_ATMEL_ADB021B:
-       case FLASH_5717VENDOR_ATMEL_ADB021D:
-       case FLASH_5717VENDOR_ATMEL_45USPT:
-               tp->nvram_jedecnum = JEDEC_ATMEL;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
+       }
 
-               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-               case FLASH_5717VENDOR_ATMEL_MDB021D:
-                       /* Detect size with tg3_nvram_get_size() */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+           tg3_flag(tp, 5780_CLASS)) {
+               switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
+               case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
+                       tp->nvram_jedecnum = JEDEC_ATMEL;
+                       tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
+                       tg3_flag_set(tp, NVRAM_BUFFERED);
                        break;
-               case FLASH_5717VENDOR_ATMEL_ADB021B:
-               case FLASH_5717VENDOR_ATMEL_ADB021D:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+               case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED:
+                       tp->nvram_jedecnum = JEDEC_ATMEL;
+                       tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE;
                        break;
-               default:
-                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+               case FLASH_VENDOR_ATMEL_EEPROM:
+                       tp->nvram_jedecnum = JEDEC_ATMEL;
+                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+                       tg3_flag_set(tp, NVRAM_BUFFERED);
                        break;
-               }
-               break;
-       case FLASH_5717VENDOR_ST_M_M25PE10:
-       case FLASH_5717VENDOR_ST_A_M25PE10:
-       case FLASH_5717VENDOR_ST_M_M45PE10:
-       case FLASH_5717VENDOR_ST_A_M45PE10:
-       case FLASH_5717VENDOR_ST_M_M25PE20:
-       case FLASH_5717VENDOR_ST_A_M25PE20:
-       case FLASH_5717VENDOR_ST_M_M45PE20:
-       case FLASH_5717VENDOR_ST_A_M45PE20:
-       case FLASH_5717VENDOR_ST_25USPT:
-       case FLASH_5717VENDOR_ST_45USPT:
-               tp->nvram_jedecnum = JEDEC_ST;
-               tg3_flag_set(tp, NVRAM_BUFFERED);
-               tg3_flag_set(tp, FLASH);
-
-               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-               case FLASH_5717VENDOR_ST_M_M25PE20:
-               case FLASH_5717VENDOR_ST_M_M45PE20:
-                       /* Detect size with tg3_nvram_get_size() */
+               case FLASH_VENDOR_ST:
+                       tp->nvram_jedecnum = JEDEC_ST;
+                       tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE;
+                       tg3_flag_set(tp, NVRAM_BUFFERED);
                        break;
-               case FLASH_5717VENDOR_ST_A_M25PE20:
-               case FLASH_5717VENDOR_ST_A_M45PE20:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+               case FLASH_VENDOR_SAIFUN:
+                       tp->nvram_jedecnum = JEDEC_SAIFUN;
+                       tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE;
                        break;
-               default:
-                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+               case FLASH_VENDOR_SST_SMALL:
+               case FLASH_VENDOR_SST_LARGE:
+                       tp->nvram_jedecnum = JEDEC_SST;
+                       tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE;
                        break;
                }
+       } else {
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+       }
+}
+
+static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+{
+       switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+       case FLASH_5752PAGE_SIZE_256:
+               tp->nvram_pagesize = 256;
+               break;
+       case FLASH_5752PAGE_SIZE_512:
+               tp->nvram_pagesize = 512;
+               break;
+       case FLASH_5752PAGE_SIZE_1K:
+               tp->nvram_pagesize = 1024;
+               break;
+       case FLASH_5752PAGE_SIZE_2K:
+               tp->nvram_pagesize = 2048;
+               break;
+       case FLASH_5752PAGE_SIZE_4K:
+               tp->nvram_pagesize = 4096;
+               break;
+       case FLASH_5752PAGE_SIZE_264:
+               tp->nvram_pagesize = 264;
+               break;
+       case FLASH_5752PAGE_SIZE_528:
+               tp->nvram_pagesize = 528;
                break;
-       default:
-               tg3_flag_set(tp, NO_NVRAM);
-               return;
        }
-
-       tg3_nvram_get_pagesize(tp, nvcfg1);
-       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
-               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
 }
 
-static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
 {
-       u32 nvcfg1, nvmpinstrp;
+       u32 nvcfg1;
 
        nvcfg1 = tr32(NVRAM_CFG1);
-       nvmpinstrp = nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK;
 
-       switch (nvmpinstrp) {
-       case FLASH_5720_EEPROM_HD:
-       case FLASH_5720_EEPROM_LD:
+       /* NVRAM protection for TPM */
+       if (nvcfg1 & (1 << 27))
+               tg3_flag_set(tp, PROTECTED_NVRAM);
+
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+       case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ:
+       case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ:
                tp->nvram_jedecnum = JEDEC_ATMEL;
                tg3_flag_set(tp, NVRAM_BUFFERED);
-
-               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-               tw32(NVRAM_CFG1, nvcfg1);
-               if (nvmpinstrp == FLASH_5720_EEPROM_HD)
-                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-               else
-                       tp->nvram_pagesize = ATMEL_AT24C02_CHIP_SIZE;
-               return;
-       case FLASH_5720VENDOR_M_ATMEL_DB011D:
-       case FLASH_5720VENDOR_A_ATMEL_DB011B:
-       case FLASH_5720VENDOR_A_ATMEL_DB011D:
-       case FLASH_5720VENDOR_M_ATMEL_DB021D:
-       case FLASH_5720VENDOR_A_ATMEL_DB021B:
-       case FLASH_5720VENDOR_A_ATMEL_DB021D:
-       case FLASH_5720VENDOR_M_ATMEL_DB041D:
-       case FLASH_5720VENDOR_A_ATMEL_DB041B:
-       case FLASH_5720VENDOR_A_ATMEL_DB041D:
-       case FLASH_5720VENDOR_M_ATMEL_DB081D:
-       case FLASH_5720VENDOR_A_ATMEL_DB081D:
-       case FLASH_5720VENDOR_ATMEL_45USPT:
+               break;
+       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
                tp->nvram_jedecnum = JEDEC_ATMEL;
                tg3_flag_set(tp, NVRAM_BUFFERED);
                tg3_flag_set(tp, FLASH);
-
-               switch (nvmpinstrp) {
-               case FLASH_5720VENDOR_M_ATMEL_DB021D:
-               case FLASH_5720VENDOR_A_ATMEL_DB021B:
-               case FLASH_5720VENDOR_A_ATMEL_DB021D:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
-                       break;
-               case FLASH_5720VENDOR_M_ATMEL_DB041D:
-               case FLASH_5720VENDOR_A_ATMEL_DB041B:
-               case FLASH_5720VENDOR_A_ATMEL_DB041D:
-                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
-                       break;
-               case FLASH_5720VENDOR_M_ATMEL_DB081D:
-               case FLASH_5720VENDOR_A_ATMEL_DB081D:
-                       tp->nvram_size = TG3_NVRAM_SIZE_1MB;
-                       break;
-               default:
-                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
-                       break;
-               }
                break;
-       case FLASH_5720VENDOR_M_ST_M25PE10:
-       case FLASH_5720VENDOR_M_ST_M45PE10:
-       case FLASH_5720VENDOR_A_ST_M25PE10:
-       case FLASH_5720VENDOR_A_ST_M45PE10:
-       case FLASH_5720VENDOR_M_ST_M25PE20:
-       case FLASH_5720VENDOR_M_ST_M45PE20:
-       case FLASH_5720VENDOR_A_ST_M25PE20:
-       case FLASH_5720VENDOR_A_ST_M45PE20:
-       case FLASH_5720VENDOR_M_ST_M25PE40:
-       case FLASH_5720VENDOR_M_ST_M45PE40:
-       case FLASH_5720VENDOR_A_ST_M25PE40:
-       case FLASH_5720VENDOR_A_ST_M45PE40:
-       case FLASH_5720VENDOR_M_ST_M25PE80:
-       case FLASH_5720VENDOR_M_ST_M45PE80:
-       case FLASH_5720VENDOR_A_ST_M25PE80:
-       case FLASH_5720VENDOR_A_ST_M45PE80:
-       case FLASH_5720VENDOR_ST_25USPT:
-       case FLASH_5720VENDOR_ST_45USPT:
+       case FLASH_5752VENDOR_ST_M45PE10:
+       case FLASH_5752VENDOR_ST_M45PE20:
+       case FLASH_5752VENDOR_ST_M45PE40:
                tp->nvram_jedecnum = JEDEC_ST;
                tg3_flag_set(tp, NVRAM_BUFFERED);
                tg3_flag_set(tp, FLASH);
-
-               switch (nvmpinstrp) {
-               case FLASH_5720VENDOR_M_ST_M25PE20:
-               case FLASH_5720VENDOR_M_ST_M45PE20:
-               case FLASH_5720VENDOR_A_ST_M25PE20:
-               case FLASH_5720VENDOR_A_ST_M45PE20:
-                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
-                       break;
-               case FLASH_5720VENDOR_M_ST_M25PE40:
-               case FLASH_5720VENDOR_M_ST_M45PE40:
-               case FLASH_5720VENDOR_A_ST_M25PE40:
-               case FLASH_5720VENDOR_A_ST_M45PE40:
-                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
-                       break;
-               case FLASH_5720VENDOR_M_ST_M25PE80:
-               case FLASH_5720VENDOR_M_ST_M45PE80:
-               case FLASH_5720VENDOR_A_ST_M25PE80:
-               case FLASH_5720VENDOR_A_ST_M45PE80:
-                       tp->nvram_size = TG3_NVRAM_SIZE_1MB;
-                       break;
-               default:
-                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
-                       break;
-               }
                break;
-       default:
-               tg3_flag_set(tp, NO_NVRAM);
-               return;
        }
 
-       tg3_nvram_get_pagesize(tp, nvcfg1);
-       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
-               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
+       if (tg3_flag(tp, FLASH)) {
+               tg3_nvram_get_pagesize(tp, nvcfg1);
+       } else {
+               /* For eeprom, set pagesize to maximum eeprom size */
+               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+       }
 }
 
-/* Chips other than 5700/5701 use the NVRAM for fetching info. */
-static void __devinit tg3_nvram_init(struct tg3 *tp)
+static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
 {
-       tw32_f(GRC_EEPROM_ADDR,
-            (EEPROM_ADDR_FSM_RESET |
-             (EEPROM_DEFAULT_CLOCK_PERIOD <<
-              EEPROM_ADDR_CLKPERD_SHIFT)));
-
-       msleep(1);
-
-       /* Enable seeprom accesses. */
-       tw32_f(GRC_LOCAL_CTRL,
-            tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
-       udelay(100);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-               tg3_flag_set(tp, NVRAM);
+       u32 nvcfg1, protect = 0;
 
-               if (tg3_nvram_lock(tp)) {
-                       netdev_warn(tp->dev,
-                                   "Cannot get nvram lock, %s failed\n",
-                                   __func__);
-                       return;
-               }
-               tg3_enable_nvram_access(tp);
+       nvcfg1 = tr32(NVRAM_CFG1);
 
-               tp->nvram_size = 0;
+       /* NVRAM protection for TPM */
+       if (nvcfg1 & (1 << 27)) {
+               tg3_flag_set(tp, PROTECTED_NVRAM);
+               protect = 1;
+       }
 
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
-                       tg3_get_5752_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
-                       tg3_get_5755_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
-                       tg3_get_5787_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
-                       tg3_get_5761_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
-                       tg3_get_5906_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
-                        tg3_flag(tp, 57765_CLASS))
-                       tg3_get_57780_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
-                       tg3_get_5717_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
-                       tg3_get_5720_nvram_info(tp);
+       nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+       switch (nvcfg1) {
+       case FLASH_5755VENDOR_ATMEL_FLASH_1:
+       case FLASH_5755VENDOR_ATMEL_FLASH_2:
+       case FLASH_5755VENDOR_ATMEL_FLASH_3:
+       case FLASH_5755VENDOR_ATMEL_FLASH_5:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
+               tp->nvram_pagesize = 264;
+               if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
+                   nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
+                       tp->nvram_size = (protect ? 0x3e200 :
+                                         TG3_NVRAM_SIZE_512KB);
+               else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
+                       tp->nvram_size = (protect ? 0x1f200 :
+                                         TG3_NVRAM_SIZE_256KB);
                else
-                       tg3_get_nvram_info(tp);
+                       tp->nvram_size = (protect ? 0x1f200 :
+                                         TG3_NVRAM_SIZE_128KB);
+               break;
+       case FLASH_5752VENDOR_ST_M45PE10:
+       case FLASH_5752VENDOR_ST_M45PE20:
+       case FLASH_5752VENDOR_ST_M45PE40:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
+               tp->nvram_pagesize = 256;
+               if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
+                       tp->nvram_size = (protect ?
+                                         TG3_NVRAM_SIZE_64KB :
+                                         TG3_NVRAM_SIZE_128KB);
+               else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
+                       tp->nvram_size = (protect ?
+                                         TG3_NVRAM_SIZE_64KB :
+                                         TG3_NVRAM_SIZE_256KB);
+               else
+                       tp->nvram_size = (protect ?
+                                         TG3_NVRAM_SIZE_128KB :
+                                         TG3_NVRAM_SIZE_512KB);
+               break;
+       }
+}
 
-               if (tp->nvram_size == 0)
-                       tg3_get_nvram_size(tp);
+static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1;
 
-               tg3_disable_nvram_access(tp);
-               tg3_nvram_unlock(tp);
+       nvcfg1 = tr32(NVRAM_CFG1);
 
-       } else {
-               tg3_flag_clear(tp, NVRAM);
-               tg3_flag_clear(tp, NVRAM_BUFFERED);
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+       case FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ:
+       case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
+       case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ:
+       case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
 
-               tg3_get_eeprom_size(tp);
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+               break;
+       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+       case FLASH_5755VENDOR_ATMEL_FLASH_1:
+       case FLASH_5755VENDOR_ATMEL_FLASH_2:
+       case FLASH_5755VENDOR_ATMEL_FLASH_3:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
+               tp->nvram_pagesize = 264;
+               break;
+       case FLASH_5752VENDOR_ST_M45PE10:
+       case FLASH_5752VENDOR_ST_M45PE20:
+       case FLASH_5752VENDOR_ST_M45PE40:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
+               tp->nvram_pagesize = 256;
+               break;
        }
 }
 
-static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
-                                   u32 offset, u32 len, u8 *buf)
+static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
 {
-       int i, j, rc = 0;
-       u32 val;
-
-       for (i = 0; i < len; i += 4) {
-               u32 addr;
-               __be32 data;
-
-               addr = offset + i;
-
-               memcpy(&data, buf + i, 4);
-
-               /*
-                * The SEEPROM interface expects the data to always be opposite
-                * the native endian format.  We accomplish this by reversing
-                * all the operations that would have been performed on the
-                * data from a call to tg3_nvram_read_be32().
-                */
-               tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data)));
+       u32 nvcfg1, protect = 0;
 
-               val = tr32(GRC_EEPROM_ADDR);
-               tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
+       nvcfg1 = tr32(NVRAM_CFG1);
 
-               val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK |
-                       EEPROM_ADDR_READ);
-               tw32(GRC_EEPROM_ADDR, val |
-                       (0 << EEPROM_ADDR_DEVID_SHIFT) |
-                       (addr & EEPROM_ADDR_ADDR_MASK) |
-                       EEPROM_ADDR_START |
-                       EEPROM_ADDR_WRITE);
+       /* NVRAM protection for TPM */
+       if (nvcfg1 & (1 << 27)) {
+               tg3_flag_set(tp, PROTECTED_NVRAM);
+               protect = 1;
+       }
 
-               for (j = 0; j < 1000; j++) {
-                       val = tr32(GRC_EEPROM_ADDR);
+       nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+       switch (nvcfg1) {
+       case FLASH_5761VENDOR_ATMEL_ADB021D:
+       case FLASH_5761VENDOR_ATMEL_ADB041D:
+       case FLASH_5761VENDOR_ATMEL_ADB081D:
+       case FLASH_5761VENDOR_ATMEL_ADB161D:
+       case FLASH_5761VENDOR_ATMEL_MDB021D:
+       case FLASH_5761VENDOR_ATMEL_MDB041D:
+       case FLASH_5761VENDOR_ATMEL_MDB081D:
+       case FLASH_5761VENDOR_ATMEL_MDB161D:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
+               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
+               tp->nvram_pagesize = 256;
+               break;
+       case FLASH_5761VENDOR_ST_A_M45PE20:
+       case FLASH_5761VENDOR_ST_A_M45PE40:
+       case FLASH_5761VENDOR_ST_A_M45PE80:
+       case FLASH_5761VENDOR_ST_A_M45PE16:
+       case FLASH_5761VENDOR_ST_M_M45PE20:
+       case FLASH_5761VENDOR_ST_M_M45PE40:
+       case FLASH_5761VENDOR_ST_M_M45PE80:
+       case FLASH_5761VENDOR_ST_M_M45PE16:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
+               tp->nvram_pagesize = 256;
+               break;
+       }
 
-                       if (val & EEPROM_ADDR_COMPLETE)
-                               break;
-                       msleep(1);
-               }
-               if (!(val & EEPROM_ADDR_COMPLETE)) {
-                       rc = -EBUSY;
+       if (protect) {
+               tp->nvram_size = tr32(NVRAM_ADDR_LOCKOUT);
+       } else {
+               switch (nvcfg1) {
+               case FLASH_5761VENDOR_ATMEL_ADB161D:
+               case FLASH_5761VENDOR_ATMEL_MDB161D:
+               case FLASH_5761VENDOR_ST_A_M45PE16:
+               case FLASH_5761VENDOR_ST_M_M45PE16:
+                       tp->nvram_size = TG3_NVRAM_SIZE_2MB;
+                       break;
+               case FLASH_5761VENDOR_ATMEL_ADB081D:
+               case FLASH_5761VENDOR_ATMEL_MDB081D:
+               case FLASH_5761VENDOR_ST_A_M45PE80:
+               case FLASH_5761VENDOR_ST_M_M45PE80:
+                       tp->nvram_size = TG3_NVRAM_SIZE_1MB;
+                       break;
+               case FLASH_5761VENDOR_ATMEL_ADB041D:
+               case FLASH_5761VENDOR_ATMEL_MDB041D:
+               case FLASH_5761VENDOR_ST_A_M45PE40:
+               case FLASH_5761VENDOR_ST_M_M45PE40:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+                       break;
+               case FLASH_5761VENDOR_ATMEL_ADB021D:
+               case FLASH_5761VENDOR_ATMEL_MDB021D:
+               case FLASH_5761VENDOR_ST_A_M45PE20:
+               case FLASH_5761VENDOR_ST_M_M45PE20:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
                        break;
                }
        }
+}
 
-       return rc;
+static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+{
+       tp->nvram_jedecnum = JEDEC_ATMEL;
+       tg3_flag_set(tp, NVRAM_BUFFERED);
+       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
 }
 
-/* offset and length are dword aligned */
-static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
-               u8 *buf)
+static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
 {
-       int ret = 0;
-       u32 pagesize = tp->nvram_pagesize;
-       u32 pagemask = pagesize - 1;
-       u32 nvram_cmd;
-       u8 *tmp;
+       u32 nvcfg1;
 
-       tmp = kmalloc(pagesize, GFP_KERNEL);
-       if (tmp == NULL)
-               return -ENOMEM;
+       nvcfg1 = tr32(NVRAM_CFG1);
 
-       while (len) {
-               int j;
-               u32 phy_addr, page_off, size;
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+       case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
+       case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
 
-               phy_addr = offset & ~pagemask;
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+               return;
+       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+       case FLASH_57780VENDOR_ATMEL_AT45DB011D:
+       case FLASH_57780VENDOR_ATMEL_AT45DB011B:
+       case FLASH_57780VENDOR_ATMEL_AT45DB021D:
+       case FLASH_57780VENDOR_ATMEL_AT45DB021B:
+       case FLASH_57780VENDOR_ATMEL_AT45DB041D:
+       case FLASH_57780VENDOR_ATMEL_AT45DB041B:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
 
-               for (j = 0; j < pagesize; j += 4) {
-                       ret = tg3_nvram_read_be32(tp, phy_addr + j,
-                                                 (__be32 *) (tmp + j));
-                       if (ret)
-                               break;
-               }
-               if (ret)
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+               case FLASH_57780VENDOR_ATMEL_AT45DB011D:
+               case FLASH_57780VENDOR_ATMEL_AT45DB011B:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
                        break;
-
-               page_off = offset & pagemask;
-               size = pagesize;
-               if (len < size)
-                       size = len;
-
-               len -= size;
-
-               memcpy(tmp + page_off, buf, size);
-
-               offset = offset + (pagesize - page_off);
-
-               tg3_enable_nvram_access(tp);
-
-               /*
-                * Before we can erase the flash page, we need
-                * to issue a special "write enable" command.
-                */
-               nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
-
-               if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+               case FLASH_57780VENDOR_ATMEL_AT45DB021D:
+               case FLASH_57780VENDOR_ATMEL_AT45DB021B:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
                        break;
-
-               /* Erase the target page */
-               tw32(NVRAM_ADDR, phy_addr);
-
-               nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR |
-                       NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE;
-
-               if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+               case FLASH_57780VENDOR_ATMEL_AT45DB041D:
+               case FLASH_57780VENDOR_ATMEL_AT45DB041B:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
                        break;
+               }
+               break;
+       case FLASH_5752VENDOR_ST_M45PE10:
+       case FLASH_5752VENDOR_ST_M45PE20:
+       case FLASH_5752VENDOR_ST_M45PE40:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
 
-               /* Issue another write enable to start the write. */
-               nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
-
-               if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5752VENDOR_ST_M45PE10:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
                        break;
-
-               for (j = 0; j < pagesize; j += 4) {
-                       __be32 data;
-
-                       data = *((__be32 *) (tmp + j));
-
-                       tw32(NVRAM_WRDATA, be32_to_cpu(data));
-
-                       tw32(NVRAM_ADDR, phy_addr + j);
-
-                       nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE |
-                               NVRAM_CMD_WR;
-
-                       if (j == 0)
-                               nvram_cmd |= NVRAM_CMD_FIRST;
-                       else if (j == (pagesize - 4))
-                               nvram_cmd |= NVRAM_CMD_LAST;
-
-                       if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd)))
-                               break;
-               }
-               if (ret)
+               case FLASH_5752VENDOR_ST_M45PE20:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               case FLASH_5752VENDOR_ST_M45PE40:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
                        break;
+               }
+               break;
+       default:
+               tg3_flag_set(tp, NO_NVRAM);
+               return;
        }
 
-       nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE;
-       tg3_nvram_exec_cmd(tp, nvram_cmd);
-
-       kfree(tmp);
-
-       return ret;
+       tg3_nvram_get_pagesize(tp, nvcfg1);
+       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
+               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
 }
 
-/* offset and length are dword aligned */
-static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
-               u8 *buf)
+
+static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
 {
-       int i, ret = 0;
+       u32 nvcfg1;
 
-       for (i = 0; i < len; i += 4, offset += 4) {
-               u32 page_off, phy_addr, nvram_cmd;
-               __be32 data;
+       nvcfg1 = tr32(NVRAM_CFG1);
 
-               memcpy(&data, buf + i, 4);
-               tw32(NVRAM_WRDATA, be32_to_cpu(data));
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+       case FLASH_5717VENDOR_ATMEL_EEPROM:
+       case FLASH_5717VENDOR_MICRO_EEPROM:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
 
-               page_off = offset % tp->nvram_pagesize;
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+               return;
+       case FLASH_5717VENDOR_ATMEL_MDB011D:
+       case FLASH_5717VENDOR_ATMEL_ADB011B:
+       case FLASH_5717VENDOR_ATMEL_ADB011D:
+       case FLASH_5717VENDOR_ATMEL_MDB021D:
+       case FLASH_5717VENDOR_ATMEL_ADB021B:
+       case FLASH_5717VENDOR_ATMEL_ADB021D:
+       case FLASH_5717VENDOR_ATMEL_45USPT:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
 
-               phy_addr = tg3_nvram_phys_addr(tp, offset);
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5717VENDOR_ATMEL_MDB021D:
+                       /* Detect size with tg3_nvram_get_size() */
+                       break;
+               case FLASH_5717VENDOR_ATMEL_ADB021B:
+               case FLASH_5717VENDOR_ATMEL_ADB021D:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               default:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
+               }
+               break;
+       case FLASH_5717VENDOR_ST_M_M25PE10:
+       case FLASH_5717VENDOR_ST_A_M25PE10:
+       case FLASH_5717VENDOR_ST_M_M45PE10:
+       case FLASH_5717VENDOR_ST_A_M45PE10:
+       case FLASH_5717VENDOR_ST_M_M25PE20:
+       case FLASH_5717VENDOR_ST_A_M25PE20:
+       case FLASH_5717VENDOR_ST_M_M45PE20:
+       case FLASH_5717VENDOR_ST_A_M45PE20:
+       case FLASH_5717VENDOR_ST_25USPT:
+       case FLASH_5717VENDOR_ST_45USPT:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
 
-               tw32(NVRAM_ADDR, phy_addr);
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5717VENDOR_ST_M_M25PE20:
+               case FLASH_5717VENDOR_ST_M_M45PE20:
+                       /* Detect size with tg3_nvram_get_size() */
+                       break;
+               case FLASH_5717VENDOR_ST_A_M25PE20:
+               case FLASH_5717VENDOR_ST_A_M45PE20:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               default:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
+               }
+               break;
+       default:
+               tg3_flag_set(tp, NO_NVRAM);
+               return;
+       }
 
-               nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR;
+       tg3_nvram_get_pagesize(tp, nvcfg1);
+       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
+               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
+}
 
-               if (page_off == 0 || i == 0)
-                       nvram_cmd |= NVRAM_CMD_FIRST;
-               if (page_off == (tp->nvram_pagesize - 4))
-                       nvram_cmd |= NVRAM_CMD_LAST;
+static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1, nvmpinstrp;
 
-               if (i == (len - 4))
-                       nvram_cmd |= NVRAM_CMD_LAST;
+       nvcfg1 = tr32(NVRAM_CFG1);
+       nvmpinstrp = nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK;
 
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
-                   !tg3_flag(tp, 5755_PLUS) &&
-                   (tp->nvram_jedecnum == JEDEC_ST) &&
-                   (nvram_cmd & NVRAM_CMD_FIRST)) {
+       switch (nvmpinstrp) {
+       case FLASH_5720_EEPROM_HD:
+       case FLASH_5720_EEPROM_LD:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
 
-                       if ((ret = tg3_nvram_exec_cmd(tp,
-                               NVRAM_CMD_WREN | NVRAM_CMD_GO |
-                               NVRAM_CMD_DONE)))
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+               if (nvmpinstrp == FLASH_5720_EEPROM_HD)
+                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+               else
+                       tp->nvram_pagesize = ATMEL_AT24C02_CHIP_SIZE;
+               return;
+       case FLASH_5720VENDOR_M_ATMEL_DB011D:
+       case FLASH_5720VENDOR_A_ATMEL_DB011B:
+       case FLASH_5720VENDOR_A_ATMEL_DB011D:
+       case FLASH_5720VENDOR_M_ATMEL_DB021D:
+       case FLASH_5720VENDOR_A_ATMEL_DB021B:
+       case FLASH_5720VENDOR_A_ATMEL_DB021D:
+       case FLASH_5720VENDOR_M_ATMEL_DB041D:
+       case FLASH_5720VENDOR_A_ATMEL_DB041B:
+       case FLASH_5720VENDOR_A_ATMEL_DB041D:
+       case FLASH_5720VENDOR_M_ATMEL_DB081D:
+       case FLASH_5720VENDOR_A_ATMEL_DB081D:
+       case FLASH_5720VENDOR_ATMEL_45USPT:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
 
-                               break;
-               }
-               if (!tg3_flag(tp, FLASH)) {
-                       /* We always do complete word writes to eeprom. */
-                       nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST);
+               switch (nvmpinstrp) {
+               case FLASH_5720VENDOR_M_ATMEL_DB021D:
+               case FLASH_5720VENDOR_A_ATMEL_DB021B:
+               case FLASH_5720VENDOR_A_ATMEL_DB021D:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               case FLASH_5720VENDOR_M_ATMEL_DB041D:
+               case FLASH_5720VENDOR_A_ATMEL_DB041B:
+               case FLASH_5720VENDOR_A_ATMEL_DB041D:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+                       break;
+               case FLASH_5720VENDOR_M_ATMEL_DB081D:
+               case FLASH_5720VENDOR_A_ATMEL_DB081D:
+                       tp->nvram_size = TG3_NVRAM_SIZE_1MB;
+                       break;
+               default:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
                }
+               break;
+       case FLASH_5720VENDOR_M_ST_M25PE10:
+       case FLASH_5720VENDOR_M_ST_M45PE10:
+       case FLASH_5720VENDOR_A_ST_M25PE10:
+       case FLASH_5720VENDOR_A_ST_M45PE10:
+       case FLASH_5720VENDOR_M_ST_M25PE20:
+       case FLASH_5720VENDOR_M_ST_M45PE20:
+       case FLASH_5720VENDOR_A_ST_M25PE20:
+       case FLASH_5720VENDOR_A_ST_M45PE20:
+       case FLASH_5720VENDOR_M_ST_M25PE40:
+       case FLASH_5720VENDOR_M_ST_M45PE40:
+       case FLASH_5720VENDOR_A_ST_M25PE40:
+       case FLASH_5720VENDOR_A_ST_M45PE40:
+       case FLASH_5720VENDOR_M_ST_M25PE80:
+       case FLASH_5720VENDOR_M_ST_M45PE80:
+       case FLASH_5720VENDOR_A_ST_M25PE80:
+       case FLASH_5720VENDOR_A_ST_M45PE80:
+       case FLASH_5720VENDOR_ST_25USPT:
+       case FLASH_5720VENDOR_ST_45USPT:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tg3_flag_set(tp, NVRAM_BUFFERED);
+               tg3_flag_set(tp, FLASH);
 
-               if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd)))
+               switch (nvmpinstrp) {
+               case FLASH_5720VENDOR_M_ST_M25PE20:
+               case FLASH_5720VENDOR_M_ST_M45PE20:
+               case FLASH_5720VENDOR_A_ST_M25PE20:
+               case FLASH_5720VENDOR_A_ST_M45PE20:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               case FLASH_5720VENDOR_M_ST_M25PE40:
+               case FLASH_5720VENDOR_M_ST_M45PE40:
+               case FLASH_5720VENDOR_A_ST_M25PE40:
+               case FLASH_5720VENDOR_A_ST_M45PE40:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+                       break;
+               case FLASH_5720VENDOR_M_ST_M25PE80:
+               case FLASH_5720VENDOR_M_ST_M45PE80:
+               case FLASH_5720VENDOR_A_ST_M25PE80:
+               case FLASH_5720VENDOR_A_ST_M45PE80:
+                       tp->nvram_size = TG3_NVRAM_SIZE_1MB;
+                       break;
+               default:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
                        break;
+               }
+               break;
+       default:
+               tg3_flag_set(tp, NO_NVRAM);
+               return;
        }
-       return ret;
+
+       tg3_nvram_get_pagesize(tp, nvcfg1);
+       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
+               tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
 }
 
-/* offset and length are dword aligned */
-static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
+/* Chips other than 5700/5701 use the NVRAM for fetching info. */
+static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
-       int ret;
+       tw32_f(GRC_EEPROM_ADDR,
+            (EEPROM_ADDR_FSM_RESET |
+             (EEPROM_DEFAULT_CLOCK_PERIOD <<
+              EEPROM_ADDR_CLKPERD_SHIFT)));
 
-       if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
-               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
-                      ~GRC_LCLCTRL_GPIO_OUTPUT1);
-               udelay(40);
-       }
+       msleep(1);
 
-       if (!tg3_flag(tp, NVRAM)) {
-               ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf);
-       } else {
-               u32 grc_mode;
+       /* Enable seeprom accesses. */
+       tw32_f(GRC_LOCAL_CTRL,
+            tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
+       udelay(100);
 
-               ret = tg3_nvram_lock(tp);
-               if (ret)
-                       return ret;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
+               tg3_flag_set(tp, NVRAM);
 
+               if (tg3_nvram_lock(tp)) {
+                       netdev_warn(tp->dev,
+                                   "Cannot get nvram lock, %s failed\n",
+                                   __func__);
+                       return;
+               }
                tg3_enable_nvram_access(tp);
-               if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM))
-                       tw32(NVRAM_WRITE1, 0x406);
 
-               grc_mode = tr32(GRC_MODE);
-               tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE);
+               tp->nvram_size = 0;
 
-               if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) {
-                       ret = tg3_nvram_write_block_buffered(tp, offset, len,
-                               buf);
-               } else {
-                       ret = tg3_nvram_write_block_unbuffered(tp, offset, len,
-                               buf);
-               }
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+                       tg3_get_5752_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+                       tg3_get_5755_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+                       tg3_get_5787_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+                       tg3_get_5761_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+                       tg3_get_5906_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+                        tg3_flag(tp, 57765_CLASS))
+                       tg3_get_57780_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+                       tg3_get_5717_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+                       tg3_get_5720_nvram_info(tp);
+               else
+                       tg3_get_nvram_info(tp);
 
-               grc_mode = tr32(GRC_MODE);
-               tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE);
+               if (tp->nvram_size == 0)
+                       tg3_get_nvram_size(tp);
 
                tg3_disable_nvram_access(tp);
                tg3_nvram_unlock(tp);
-       }
 
-       if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
-               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-               udelay(40);
-       }
+       } else {
+               tg3_flag_clear(tp, NVRAM);
+               tg3_flag_clear(tp, NVRAM_BUFFERED);
 
-       return ret;
+               tg3_get_eeprom_size(tp);
+       }
 }
 
 struct subsys_tbl_ent {
@@ -13329,14 +13368,13 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
                adv |= ADVERTISED_FIBRE;
 
        tp->link_config.advertising = adv;
-       tp->link_config.speed = SPEED_INVALID;
-       tp->link_config.duplex = DUPLEX_INVALID;
+       tp->link_config.speed = SPEED_UNKNOWN;
+       tp->link_config.duplex = DUPLEX_UNKNOWN;
        tp->link_config.autoneg = AUTONEG_ENABLE;
-       tp->link_config.active_speed = SPEED_INVALID;
-       tp->link_config.active_duplex = DUPLEX_INVALID;
-       tp->link_config.orig_speed = SPEED_INVALID;
-       tp->link_config.orig_duplex = DUPLEX_INVALID;
-       tp->link_config.orig_autoneg = AUTONEG_INVALID;
+       tp->link_config.active_speed = SPEED_UNKNOWN;
+       tp->link_config.active_duplex = DUPLEX_UNKNOWN;
+
+       tp->old_link = -1;
 }
 
 static int __devinit tg3_phy_probe(struct tg3 *tp)
@@ -13833,8 +13871,6 @@ done:
        tp->fw_ver[TG3_VER_SIZE - 1] = 0;
 }
 
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
-
 static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
 {
        if (tg3_flag(tp, LRG_PROD_RING_CAP))
@@ -13852,49 +13888,50 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
        { },
 };
 
-static int __devinit tg3_get_invariants(struct tg3 *tp)
+static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
 {
-       u32 misc_ctrl_reg;
-       u32 pci_state_reg, grc_misc_cfg;
-       u32 val;
-       u16 pci_cmd;
-       int err;
+       struct pci_dev *peer;
+       unsigned int func, devnr = tp->pdev->devfn & ~7;
 
-       /* Force memory write invalidate off.  If we leave it on,
-        * then on 5700_BX chips we have to enable a workaround.
-        * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
-        * to match the cacheline size.  The Broadcom driver have this
-        * workaround but turns MWI off all the times so never uses
-        * it.  This seems to suggest that the workaround is insufficient.
+       for (func = 0; func < 8; func++) {
+               peer = pci_get_slot(tp->pdev->bus, devnr | func);
+               if (peer && peer != tp->pdev)
+                       break;
+               pci_dev_put(peer);
+       }
+       /* 5704 can be configured in single-port mode, set peer to
+        * tp->pdev in that case.
         */
-       pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
-       pci_cmd &= ~PCI_COMMAND_INVALIDATE;
-       pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+       if (!peer) {
+               peer = tp->pdev;
+               return peer;
+       }
 
-       /* Important! -- Make sure register accesses are byteswapped
-        * correctly.  Also, for those chips that require it, make
-        * sure that indirect register accesses are enabled before
-        * the first operation.
+       /*
+        * We don't need to keep the refcount elevated; there's no way
+        * to remove one half of this device without removing the other
         */
-       pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-                             &misc_ctrl_reg);
-       tp->misc_host_ctrl |= (misc_ctrl_reg &
-                              MISC_HOST_CTRL_CHIPREV);
-       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-                              tp->misc_host_ctrl);
+       pci_dev_put(peer);
 
-       tp->pci_chip_rev_id = (misc_ctrl_reg >>
-                              MISC_HOST_CTRL_CHIPREV_SHIFT);
+       return peer;
+}
+
+static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
+{
+       tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
-               u32 prod_id_asic_rev;
+               u32 reg;
+
+               /* All devices that use the alternate
+                * ASIC REV location have a CPMU.
+                */
+               tg3_flag_set(tp, CPMU_PRESENT);
 
                if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
-                       pci_read_config_dword(tp->pdev,
-                                             TG3PCI_GEN2_PRODID_ASICREV,
-                                             &prod_id_asic_rev);
+                       reg = TG3PCI_GEN2_PRODID_ASICREV;
                else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
                         tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
                         tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 ||
@@ -13905,14 +13942,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                         tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 ||
                         tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782 ||
                         tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786)
-                       pci_read_config_dword(tp->pdev,
-                                             TG3PCI_GEN15_PRODID_ASICREV,
-                                             &prod_id_asic_rev);
+                       reg = TG3PCI_GEN15_PRODID_ASICREV;
                else
-                       pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
-                                             &prod_id_asic_rev);
+                       reg = TG3PCI_PRODID_ASICREV;
 
-               tp->pci_chip_rev_id = prod_id_asic_rev;
+               pci_read_config_dword(tp->pdev, reg, &tp->pci_chip_rev_id);
        }
 
        /* Wrong chip ID in 5752 A0. This code can be removed later
@@ -13921,6 +13955,77 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
                tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               tg3_flag_set(tp, 5717_PLUS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
+               tg3_flag_set(tp, 57765_CLASS);
+
+       if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS))
+               tg3_flag_set(tp, 57765_PLUS);
+
+       /* Intentionally exclude ASIC_REV_5906 */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+           tg3_flag(tp, 57765_PLUS))
+               tg3_flag_set(tp, 5755_PLUS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)
+               tg3_flag_set(tp, 5780_CLASS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+           tg3_flag(tp, 5755_PLUS) ||
+           tg3_flag(tp, 5780_CLASS))
+               tg3_flag_set(tp, 5750_PLUS);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+           tg3_flag(tp, 5750_PLUS))
+               tg3_flag_set(tp, 5705_PLUS);
+}
+
+static int __devinit tg3_get_invariants(struct tg3 *tp)
+{
+       u32 misc_ctrl_reg;
+       u32 pci_state_reg, grc_misc_cfg;
+       u32 val;
+       u16 pci_cmd;
+       int err;
+
+       /* Force memory write invalidate off.  If we leave it on,
+        * then on 5700_BX chips we have to enable a workaround.
+        * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
+        * to match the cacheline size.  The Broadcom driver have this
+        * workaround but turns MWI off all the times so never uses
+        * it.  This seems to suggest that the workaround is insufficient.
+        */
+       pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+       pci_cmd &= ~PCI_COMMAND_INVALIDATE;
+       pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+
+       /* Important! -- Make sure register accesses are byteswapped
+        * correctly.  Also, for those chips that require it, make
+        * sure that indirect register accesses are enabled before
+        * the first operation.
+        */
+       pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                             &misc_ctrl_reg);
+       tp->misc_host_ctrl |= (misc_ctrl_reg &
+                              MISC_HOST_CTRL_CHIPREV);
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
+
+       tg3_detect_asic_rev(tp, misc_ctrl_reg);
+
        /* If we have 5702/03 A1 or A2 on certain ICH chipsets,
         * we need to disable memory and use config. cycles
         * only to access all registers. The 5702/03 chips
@@ -14017,9 +14122,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         * Any tg3 device found behind the bridge will also need the 40-bit
         * DMA workaround.
         */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
-               tg3_flag_set(tp, 5780_CLASS);
+       if (tg3_flag(tp, 5780_CLASS)) {
                tg3_flag_set(tp, 40BIT_DMA_BUG);
                tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
        } else {
@@ -14045,39 +14148,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)
                tp->pdev_peer = tg3_find_peer(tp);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
-               tg3_flag_set(tp, 5717_PLUS);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
-               tg3_flag_set(tp, 57765_CLASS);
-
-       if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS))
-               tg3_flag_set(tp, 57765_PLUS);
-
-       /* Intentionally exclude ASIC_REV_5906 */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
-           tg3_flag(tp, 57765_PLUS))
-               tg3_flag_set(tp, 5755_PLUS);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
-           tg3_flag(tp, 5755_PLUS) ||
-           tg3_flag(tp, 5780_CLASS))
-               tg3_flag_set(tp, 5750_PLUS);
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-           tg3_flag(tp, 5750_PLUS))
-               tg3_flag_set(tp, 5705_PLUS);
-
        /* Determine TSO capabilities */
        if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0)
                ; /* Do nothing. HW bug. */
@@ -14149,8 +14219,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
                tp->dma_limit = TG3_TX_BD_DMA_MAX_4K;
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
-               tp->dma_limit = TG3_TX_BD_DMA_MAX_2K;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
@@ -14174,12 +14242,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
                tg3_flag_set(tp, PCI_EXPRESS);
 
-               if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) {
-                       int readrq = pcie_get_readrq(tp->pdev);
-                       if (readrq > 2048)
-                               pcie_set_readrq(tp->pdev, 2048);
-               }
-
                pci_read_config_word(tp->pdev,
                                     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
                                     &lnkctl);
@@ -14409,13 +14471,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tg3_ape_lock_init(tp);
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
-           tg3_flag(tp, 57765_PLUS))
-               tg3_flag_set(tp, CPMU_PRESENT);
-
        /* Set up tp->grc_local_ctrl before calling
         * tg3_pwrsrc_switch_to_vmain().  GPIO1 driven high
         * will bring 5700's external PHY out of reset.
@@ -15350,34 +15405,6 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
        return str;
 }
 
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
-{
-       struct pci_dev *peer;
-       unsigned int func, devnr = tp->pdev->devfn & ~7;
-
-       for (func = 0; func < 8; func++) {
-               peer = pci_get_slot(tp->pdev->bus, devnr | func);
-               if (peer && peer != tp->pdev)
-                       break;
-               pci_dev_put(peer);
-       }
-       /* 5704 can be configured in single-port mode, set peer to
-        * tp->pdev in that case.
-        */
-       if (!peer) {
-               peer = tp->pdev;
-               return peer;
-       }
-
-       /*
-        * We don't need to keep the refcount elevated; there's no way
-        * to remove one half of this device without removing the other
-        */
-       pci_dev_put(peer);
-
-       return peer;
-}
-
 static void __devinit tg3_init_coal(struct tg3 *tp)
 {
        struct ethtool_coalesce *ec = &tp->coal;
@@ -15409,24 +15436,6 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
        }
 }
 
-static const struct net_device_ops tg3_netdev_ops = {
-       .ndo_open               = tg3_open,
-       .ndo_stop               = tg3_close,
-       .ndo_start_xmit         = tg3_start_xmit,
-       .ndo_get_stats64        = tg3_get_stats64,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_rx_mode        = tg3_set_rx_mode,
-       .ndo_set_mac_address    = tg3_set_mac_addr,
-       .ndo_do_ioctl           = tg3_ioctl,
-       .ndo_tx_timeout         = tg3_tx_timeout,
-       .ndo_change_mtu         = tg3_change_mtu,
-       .ndo_fix_features       = tg3_fix_features,
-       .ndo_set_features       = tg3_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = tg3_poll_controller,
-#endif
-};
-
 static int __devinit tg3_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
@@ -15471,7 +15480,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
        if (!dev) {
-               dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");
                err = -ENOMEM;
                goto err_out_power_down;
        }
@@ -15728,6 +15736,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                tg3_frob_aux_power(tp, false);
        }
 
+       tg3_timer_init(tp);
+
        err = register_netdev(dev);
        if (err) {
                dev_err(&pdev->dev, "Cannot register net device, aborting\n");
@@ -15853,7 +15863,7 @@ static int tg3_suspend(struct device *device)
        tg3_phy_stop(tp);
        tg3_netif_stop(tp);
 
-       del_timer_sync(&tp->timer);
+       tg3_timer_stop(tp);
 
        tg3_full_lock(tp, 1);
        tg3_disable_ints(tp);
@@ -15877,8 +15887,7 @@ static int tg3_suspend(struct device *device)
                if (err2)
                        goto out;
 
-               tp->timer.expires = jiffies + tp->timer_offset;
-               add_timer(&tp->timer);
+               tg3_timer_start(tp);
 
                netif_device_attach(dev);
                tg3_netif_start(tp);
@@ -15912,8 +15921,7 @@ static int tg3_resume(struct device *device)
        if (err)
                goto out;
 
-       tp->timer.expires = jiffies + tp->timer_offset;
-       add_timer(&tp->timer);
+       tg3_timer_start(tp);
 
        tg3_netif_start(tp);
 
@@ -15961,11 +15969,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
        tg3_netif_stop(tp);
 
-       del_timer_sync(&tp->timer);
+       tg3_timer_stop(tp);
 
        /* Want to make sure that the reset task doesn't run */
        tg3_reset_task_cancel(tp);
-       tg3_flag_clear(tp, TX_RECOVERY_PENDING);
 
        netif_device_detach(netdev);
 
@@ -16058,8 +16065,7 @@ static void tg3_io_resume(struct pci_dev *pdev)
 
        netif_device_attach(netdev);
 
-       tp->timer.expires = jiffies + tp->timer_offset;
-       add_timer(&tp->timer);
+       tg3_timer_start(tp);
 
        tg3_netif_start(tp);