ethtool: allow custom interval for physical identification
[linux-2.6-block.git] / drivers / net / tg3.c
index 53a1209d4f9c2123d8c825629ddef4400e25dda0..9915734ac3e9e64a1682680ffd9f3fe8a98a4f11 100644 (file)
 
 #define TG3_RAW_IP_ALIGN 2
 
-/* number of ETHTOOL_GSTATS u64's */
-#define TG3_NUM_STATS          (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
-
-#define TG3_NUM_TEST           6
-
 #define TG3_FW_UPDATE_TIMEOUT_SEC      5
 
 #define FIRMWARE_TG3           "tigon/tg3.bin"
@@ -264,6 +259,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -278,7 +274,7 @@ MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);
 
 static const struct {
        const char string[ETH_GSTRING_LEN];
-} ethtool_stats_keys[TG3_NUM_STATS] = {
+} ethtool_stats_keys[] = {
        { "rx_octets" },
        { "rx_fragments" },
        { "rx_ucast_packets" },
@@ -357,9 +353,12 @@ static const struct {
        { "nic_tx_threshold_hit" }
 };
 
+#define TG3_NUM_STATS  ARRAY_SIZE(ethtool_stats_keys)
+
+
 static const struct {
        const char string[ETH_GSTRING_LEN];
-} ethtool_test_keys[TG3_NUM_TEST] = {
+} ethtool_test_keys[] = {
        { "nvram test     (online) " },
        { "link test      (online) " },
        { "register test  (offline)" },
@@ -368,6 +367,9 @@ static const struct {
        { "interrupt test (offline)" },
 };
 
+#define TG3_NUM_TEST   ARRAY_SIZE(ethtool_test_keys)
+
+
 static void tg3_write32(struct tg3 *tp, u32 off, u32 val)
 {
        writel(val, tp->regs + off);
@@ -4390,6 +4392,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
 
 static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 {
+       u32 val;
        int err;
 
        if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
@@ -4400,7 +4403,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                err = tg3_setup_copper_phy(tp, force_reset);
 
        if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
-               u32 val, scale;
+               u32 scale;
 
                val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
                if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
@@ -4415,17 +4418,20 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                tw32(GRC_MISC_CFG, val);
        }
 
+       val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+             (6 << TX_LENGTHS_IPG_SHIFT);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               val |= tr32(MAC_TX_LENGTHS) &
+                      (TX_LENGTHS_JMB_FRM_LEN_MSK |
+                       TX_LENGTHS_CNT_DWN_VAL_MSK);
+
        if (tp->link_config.active_speed == SPEED_1000 &&
            tp->link_config.active_duplex == DUPLEX_HALF)
-               tw32(MAC_TX_LENGTHS,
-                    ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
-                     (6 << TX_LENGTHS_IPG_SHIFT) |
-                     (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
+               tw32(MAC_TX_LENGTHS, val |
+                    (0xff << TX_LENGTHS_SLOT_TIME_SHIFT));
        else
-               tw32(MAC_TX_LENGTHS,
-                    ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
-                     (6 << TX_LENGTHS_IPG_SHIFT) |
-                     (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
+               tw32(MAC_TX_LENGTHS, val |
+                    (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
 
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
                if (netif_carrier_ok(tp->dev)) {
@@ -4437,7 +4443,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
        }
 
        if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) {
-               u32 val = tr32(PCIE_PWR_MGMT_THRESH);
+               val = tr32(PCIE_PWR_MGMT_THRESH);
                if (!netif_carrier_ok(tp->dev))
                        val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
                              tp->pwrmgmt_thresh;
@@ -4454,6 +4460,123 @@ static inline int tg3_irq_sync(struct tg3 *tp)
        return tp->irq_sync;
 }
 
+static inline void tg3_rd32_loop(struct tg3 *tp, u32 *dst, u32 off, u32 len)
+{
+       int i;
+
+       dst = (u32 *)((u8 *)dst + off);
+       for (i = 0; i < len; i += sizeof(u32))
+               *dst++ = tr32(off + i);
+}
+
+static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs)
+{
+       tg3_rd32_loop(tp, regs, TG3PCI_VENDOR, 0xb0);
+       tg3_rd32_loop(tp, regs, MAILBOX_INTERRUPT_0, 0x200);
+       tg3_rd32_loop(tp, regs, MAC_MODE, 0x4f0);
+       tg3_rd32_loop(tp, regs, SNDDATAI_MODE, 0xe0);
+       tg3_rd32_loop(tp, regs, SNDDATAC_MODE, 0x04);
+       tg3_rd32_loop(tp, regs, SNDBDS_MODE, 0x80);
+       tg3_rd32_loop(tp, regs, SNDBDI_MODE, 0x48);
+       tg3_rd32_loop(tp, regs, SNDBDC_MODE, 0x04);
+       tg3_rd32_loop(tp, regs, RCVLPC_MODE, 0x20);
+       tg3_rd32_loop(tp, regs, RCVLPC_SELLST_BASE, 0x15c);
+       tg3_rd32_loop(tp, regs, RCVDBDI_MODE, 0x0c);
+       tg3_rd32_loop(tp, regs, RCVDBDI_JUMBO_BD, 0x3c);
+       tg3_rd32_loop(tp, regs, RCVDBDI_BD_PROD_IDX_0, 0x44);
+       tg3_rd32_loop(tp, regs, RCVDCC_MODE, 0x04);
+       tg3_rd32_loop(tp, regs, RCVBDI_MODE, 0x20);
+       tg3_rd32_loop(tp, regs, RCVCC_MODE, 0x14);
+       tg3_rd32_loop(tp, regs, RCVLSC_MODE, 0x08);
+       tg3_rd32_loop(tp, regs, MBFREE_MODE, 0x08);
+       tg3_rd32_loop(tp, regs, HOSTCC_MODE, 0x100);
+
+       if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX)
+               tg3_rd32_loop(tp, regs, HOSTCC_RXCOL_TICKS_VEC1, 0x180);
+
+       tg3_rd32_loop(tp, regs, MEMARB_MODE, 0x10);
+       tg3_rd32_loop(tp, regs, BUFMGR_MODE, 0x58);
+       tg3_rd32_loop(tp, regs, RDMAC_MODE, 0x08);
+       tg3_rd32_loop(tp, regs, WDMAC_MODE, 0x08);
+       tg3_rd32_loop(tp, regs, RX_CPU_MODE, 0x04);
+       tg3_rd32_loop(tp, regs, RX_CPU_STATE, 0x04);
+       tg3_rd32_loop(tp, regs, RX_CPU_PGMCTR, 0x04);
+       tg3_rd32_loop(tp, regs, RX_CPU_HWBKPT, 0x04);
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+               tg3_rd32_loop(tp, regs, TX_CPU_MODE, 0x04);
+               tg3_rd32_loop(tp, regs, TX_CPU_STATE, 0x04);
+               tg3_rd32_loop(tp, regs, TX_CPU_PGMCTR, 0x04);
+       }
+
+       tg3_rd32_loop(tp, regs, GRCMBOX_INTERRUPT_0, 0x110);
+       tg3_rd32_loop(tp, regs, FTQ_RESET, 0x120);
+       tg3_rd32_loop(tp, regs, MSGINT_MODE, 0x0c);
+       tg3_rd32_loop(tp, regs, DMAC_MODE, 0x04);
+       tg3_rd32_loop(tp, regs, GRC_MODE, 0x4c);
+
+       if (tp->tg3_flags & TG3_FLAG_NVRAM)
+               tg3_rd32_loop(tp, regs, NVRAM_CMD, 0x24);
+}
+
+static void tg3_dump_state(struct tg3 *tp)
+{
+       int i;
+       u32 *regs;
+
+       regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC);
+       if (!regs) {
+               netdev_err(tp->dev, "Failed allocating register dump buffer\n");
+               return;
+       }
+
+       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+               /* Read up to but not including private PCI registers */
+               for (i = 0; i < TG3_PCIE_TLDLPL_PORT; i += sizeof(u32))
+                       regs[i / sizeof(u32)] = tr32(i);
+       } else
+               tg3_dump_legacy_regs(tp, regs);
+
+       for (i = 0; i < TG3_REG_BLK_SIZE / sizeof(u32); i += 4) {
+               if (!regs[i + 0] && !regs[i + 1] &&
+                   !regs[i + 2] && !regs[i + 3])
+                       continue;
+
+               netdev_err(tp->dev, "0x%08x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+                          i * 4,
+                          regs[i + 0], regs[i + 1], regs[i + 2], regs[i + 3]);
+       }
+
+       kfree(regs);
+
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+
+               /* SW status block */
+               netdev_err(tp->dev,
+                        "%d: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n",
+                          i,
+                          tnapi->hw_status->status,
+                          tnapi->hw_status->status_tag,
+                          tnapi->hw_status->rx_jumbo_consumer,
+                          tnapi->hw_status->rx_consumer,
+                          tnapi->hw_status->rx_mini_consumer,
+                          tnapi->hw_status->idx[0].rx_producer,
+                          tnapi->hw_status->idx[0].tx_consumer);
+
+               netdev_err(tp->dev,
+               "%d: NAPI info [%08x:%08x:(%04x:%04x:%04x):%04x:(%04x:%04x:%04x:%04x)]\n",
+                          i,
+                          tnapi->last_tag, tnapi->last_irq_tag,
+                          tnapi->tx_prod, tnapi->tx_cons, tnapi->tx_pending,
+                          tnapi->rx_rcb_ptr,
+                          tnapi->prodring.rx_std_prod_idx,
+                          tnapi->prodring.rx_std_cons_idx,
+                          tnapi->prodring.rx_jmb_prod_idx,
+                          tnapi->prodring.rx_jmb_cons_idx);
+       }
+}
+
 /* This is called whenever we suspect that the system chipset is re-
  * ordering the sequence of MMIO to the tx send mailbox. The symptom
  * is bogus tx completions. We try to recover by setting the
@@ -4811,7 +4934,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                        skb = copy_skb;
                }
 
-               if ((tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) &&
+               if ((tp->dev->features & NETIF_F_RXCSUM) &&
                    (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
                    (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
                      >> RXD_TCPCSUM_SHIFT) == 0xffff))
@@ -5137,6 +5260,40 @@ tx_recovery:
        return work_done;
 }
 
+static void tg3_process_error(struct tg3 *tp)
+{
+       u32 val;
+       bool real_error = false;
+
+       if (tp->tg3_flags & TG3_FLAG_ERROR_PROCESSED)
+               return;
+
+       /* Check Flow Attention register */
+       val = tr32(HOSTCC_FLOW_ATTN);
+       if (val & ~HOSTCC_FLOW_ATTN_MBUF_LWM) {
+               netdev_err(tp->dev, "FLOW Attention error.  Resetting chip.\n");
+               real_error = true;
+       }
+
+       if (tr32(MSGINT_STATUS) & ~MSGINT_STATUS_MSI_REQ) {
+               netdev_err(tp->dev, "MSI Status error.  Resetting chip.\n");
+               real_error = true;
+       }
+
+       if (tr32(RDMAC_STATUS) || tr32(WDMAC_STATUS)) {
+               netdev_err(tp->dev, "DMA Status error.  Resetting chip.\n");
+               real_error = true;
+       }
+
+       if (!real_error)
+               return;
+
+       tg3_dump_state(tp);
+
+       tp->tg3_flags |= TG3_FLAG_ERROR_PROCESSED;
+       schedule_work(&tp->reset_task);
+}
+
 static int tg3_poll(struct napi_struct *napi, int budget)
 {
        struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi);
@@ -5145,6 +5302,9 @@ static int tg3_poll(struct napi_struct *napi, int budget)
        struct tg3_hw_status *sblk = tnapi->hw_status;
 
        while (1) {
+               if (sblk->status & SD_STATUS_ERROR)
+                       tg3_process_error(tp);
+
                tg3_poll_link(tp);
 
                work_done = tg3_poll_work(tnapi, work_done, budget);
@@ -5511,21 +5671,13 @@ out:
                tg3_phy_start(tp);
 }
 
-static void tg3_dump_short_state(struct tg3 *tp)
-{
-       netdev_err(tp->dev, "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n",
-                  tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS));
-       netdev_err(tp->dev, "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n",
-                  tr32(RDMAC_STATUS), tr32(WDMAC_STATUS));
-}
-
 static void tg3_tx_timeout(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
        if (netif_msg_tx_err(tp)) {
                netdev_err(dev, "transmit timed out, resetting\n");
-               tg3_dump_short_state(tp);
+               tg3_dump_state(tp);
        }
 
        schedule_work(&tp->reset_task);
@@ -6122,6 +6274,16 @@ dma_error:
        return NETDEV_TX_OK;
 }
 
+static u32 tg3_fix_features(struct net_device *dev, u32 features)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       if (dev->mtu > ETH_DATA_LEN && (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
+               features &= ~NETIF_F_ALL_TSO;
+
+       return features;
+}
+
 static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
                               int new_mtu)
 {
@@ -6129,14 +6291,16 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
 
        if (new_mtu > ETH_DATA_LEN) {
                if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+                       netdev_update_features(dev);
                        tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
-                       ethtool_op_set_tso(dev, 0);
                } else {
                        tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
                }
        } else {
-               if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+               if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
                        tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
+                       netdev_update_features(dev);
+               }
                tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE;
        }
 }
@@ -7190,7 +7354,8 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        tg3_restore_pci_state(tp);
 
-       tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+       tp->tg3_flags &= ~(TG3_FLAG_CHIP_RESETTING |
+                          TG3_FLAG_ERROR_PROCESSED);
 
        val = 0;
        if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
@@ -8164,10 +8329,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        /* The slot time is changed by tg3_setup_phy if we
         * run at gigabit with half duplex.
         */
-       tw32(MAC_TX_LENGTHS,
-            (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
-            (6 << TX_LENGTHS_IPG_SHIFT) |
-            (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
+       val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+             (6 << TX_LENGTHS_IPG_SHIFT) |
+             (32 << TX_LENGTHS_SLOT_TIME_SHIFT);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               val |= tr32(MAC_TX_LENGTHS) &
+                      (TX_LENGTHS_JMB_FRM_LEN_MSK |
+                       TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+       tw32(MAC_TX_LENGTHS, val);
 
        /* Receive rules. */
        tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS);
@@ -8214,6 +8385,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               rdmac_mode |= tr32(RDMAC_MODE) & RDMAC_MODE_H2BNC_VLAN_DET;
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
@@ -8447,9 +8621,17 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        }
 
        tp->tx_mode = TX_MODE_ENABLE;
+
        if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+               val = TX_MODE_JMB_FRM_LEN | TX_MODE_CNT_DN_MODE;
+               tp->tx_mode &= ~val;
+               tp->tx_mode |= tr32(MAC_TX_MODE) & val;
+       }
+
        tw32_f(MAC_TX_MODE, tp->tx_mode);
        udelay(100);
 
@@ -9590,82 +9772,26 @@ static void tg3_set_rx_mode(struct net_device *dev)
        tg3_full_unlock(tp);
 }
 
-#define TG3_REGDUMP_LEN                (32 * 1024)
-
 static int tg3_get_regs_len(struct net_device *dev)
 {
-       return TG3_REGDUMP_LEN;
+       return TG3_REG_BLK_SIZE;
 }
 
 static void tg3_get_regs(struct net_device *dev,
                struct ethtool_regs *regs, void *_p)
 {
-       u32 *p = _p;
        struct tg3 *tp = netdev_priv(dev);
-       u8 *orig_p = _p;
-       int i;
 
        regs->version = 0;
 
-       memset(p, 0, TG3_REGDUMP_LEN);
+       memset(_p, 0, TG3_REG_BLK_SIZE);
 
        if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
                return;
 
        tg3_full_lock(tp, 0);
 
-#define __GET_REG32(reg)       (*(p)++ = tr32(reg))
-#define GET_REG32_LOOP(base, len)              \
-do {   p = (u32 *)(orig_p + (base));           \
-       for (i = 0; i < len; i += 4)            \
-               __GET_REG32((base) + i);        \
-} while (0)
-#define GET_REG32_1(reg)                       \
-do {   p = (u32 *)(orig_p + (reg));            \
-       __GET_REG32((reg));                     \
-} while (0)
-
-       GET_REG32_LOOP(TG3PCI_VENDOR, 0xb0);
-       GET_REG32_LOOP(MAILBOX_INTERRUPT_0, 0x200);
-       GET_REG32_LOOP(MAC_MODE, 0x4f0);
-       GET_REG32_LOOP(SNDDATAI_MODE, 0xe0);
-       GET_REG32_1(SNDDATAC_MODE);
-       GET_REG32_LOOP(SNDBDS_MODE, 0x80);
-       GET_REG32_LOOP(SNDBDI_MODE, 0x48);
-       GET_REG32_1(SNDBDC_MODE);
-       GET_REG32_LOOP(RCVLPC_MODE, 0x20);
-       GET_REG32_LOOP(RCVLPC_SELLST_BASE, 0x15c);
-       GET_REG32_LOOP(RCVDBDI_MODE, 0x0c);
-       GET_REG32_LOOP(RCVDBDI_JUMBO_BD, 0x3c);
-       GET_REG32_LOOP(RCVDBDI_BD_PROD_IDX_0, 0x44);
-       GET_REG32_1(RCVDCC_MODE);
-       GET_REG32_LOOP(RCVBDI_MODE, 0x20);
-       GET_REG32_LOOP(RCVCC_MODE, 0x14);
-       GET_REG32_LOOP(RCVLSC_MODE, 0x08);
-       GET_REG32_1(MBFREE_MODE);
-       GET_REG32_LOOP(HOSTCC_MODE, 0x100);
-       GET_REG32_LOOP(MEMARB_MODE, 0x10);
-       GET_REG32_LOOP(BUFMGR_MODE, 0x58);
-       GET_REG32_LOOP(RDMAC_MODE, 0x08);
-       GET_REG32_LOOP(WDMAC_MODE, 0x08);
-       GET_REG32_1(RX_CPU_MODE);
-       GET_REG32_1(RX_CPU_STATE);
-       GET_REG32_1(RX_CPU_PGMCTR);
-       GET_REG32_1(RX_CPU_HWBKPT);
-       GET_REG32_1(TX_CPU_MODE);
-       GET_REG32_1(TX_CPU_STATE);
-       GET_REG32_1(TX_CPU_PGMCTR);
-       GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110);
-       GET_REG32_LOOP(FTQ_RESET, 0x120);
-       GET_REG32_LOOP(MSGINT_MODE, 0x0c);
-       GET_REG32_1(DMAC_MODE);
-       GET_REG32_LOOP(GRC_MODE, 0x4c);
-       if (tp->tg3_flags & TG3_FLAG_NVRAM)
-               GET_REG32_LOOP(NVRAM_CMD, 0x24);
-
-#undef __GET_REG32
-#undef GET_REG32_LOOP
-#undef GET_REG32_1
+       tg3_dump_legacy_regs(tp, (u32 *)_p);
 
        tg3_full_unlock(tp);
 }
@@ -9714,7 +9840,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                eeprom->len += b_count;
        }
 
-       /* read bytes upto the last 4 byte boundary */
+       /* read bytes up to the last 4 byte boundary */
        pd = &data[eeprom->len];
        for (i = 0; i < (len - (len & 3)); i += 4) {
                ret = tg3_nvram_read_be32(tp, offset + i, &val);
@@ -9999,33 +10125,6 @@ static void tg3_set_msglevel(struct net_device *dev, u32 value)
        tp->msg_enable = value;
 }
 
-static int tg3_set_tso(struct net_device *dev, u32 value)
-{
-       struct tg3 *tp = netdev_priv(dev);
-
-       if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
-               if (value)
-                       return -EINVAL;
-               return 0;
-       }
-       if ((dev->features & NETIF_F_IPV6_CSUM) &&
-           ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
-            (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3))) {
-               if (value) {
-                       dev->features |= NETIF_F_TSO6;
-                       if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
-                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-                           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
-                            GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
-                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
-                               dev->features |= NETIF_F_TSO_ECN;
-               } else
-                       dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
-       }
-       return ethtool_op_set_tso(dev, value);
-}
-
 static int tg3_nway_reset(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
@@ -10248,50 +10347,6 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
        return err;
 }
 
-static u32 tg3_get_rx_csum(struct net_device *dev)
-{
-       struct tg3 *tp = netdev_priv(dev);
-       return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0;
-}
-
-static int tg3_set_rx_csum(struct net_device *dev, u32 data)
-{
-       struct tg3 *tp = netdev_priv(dev);
-
-       if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) {
-               if (data != 0)
-                       return -EINVAL;
-               return 0;
-       }
-
-       spin_lock_bh(&tp->lock);
-       if (data)
-               tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
-       else
-               tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
-       spin_unlock_bh(&tp->lock);
-
-       return 0;
-}
-
-static int tg3_set_tx_csum(struct net_device *dev, u32 data)
-{
-       struct tg3 *tp = netdev_priv(dev);
-
-       if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) {
-               if (data != 0)
-                       return -EINVAL;
-               return 0;
-       }
-
-       if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
-               ethtool_op_set_tx_ipv6_csum(dev, data);
-       else
-               ethtool_op_set_tx_csum(dev, data);
-
-       return 0;
-}
-
 static int tg3_get_sset_count(struct net_device *dev, int sset)
 {
        switch (sset) {
@@ -10319,35 +10374,38 @@ static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
        }
 }
 
-static int tg3_phys_id(struct net_device *dev, u32 data)
+static int tg3_set_phys_id(struct net_device *dev,
+                           enum ethtool_phys_id_state state)
 {
        struct tg3 *tp = netdev_priv(dev);
-       int i;
 
        if (!netif_running(tp->dev))
                return -EAGAIN;
 
-       if (data == 0)
-               data = UINT_MAX / 2;
-
-       for (i = 0; i < (data * 2); i++) {
-               if ((i % 2) == 0)
-                       tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
-                                          LED_CTRL_1000MBPS_ON |
-                                          LED_CTRL_100MBPS_ON |
-                                          LED_CTRL_10MBPS_ON |
-                                          LED_CTRL_TRAFFIC_OVERRIDE |
-                                          LED_CTRL_TRAFFIC_BLINK |
-                                          LED_CTRL_TRAFFIC_LED);
+       switch (state) {
+       case ETHTOOL_ID_ACTIVE:
+               return 1;       /* cycle on/off once per second */
+
+       case ETHTOOL_ID_ON:
+               tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+                    LED_CTRL_1000MBPS_ON |
+                    LED_CTRL_100MBPS_ON |
+                    LED_CTRL_10MBPS_ON |
+                    LED_CTRL_TRAFFIC_OVERRIDE |
+                    LED_CTRL_TRAFFIC_BLINK |
+                    LED_CTRL_TRAFFIC_LED);
+               break;
 
-               else
-                       tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
-                                          LED_CTRL_TRAFFIC_OVERRIDE);
+       case ETHTOOL_ID_OFF:
+               tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+                    LED_CTRL_TRAFFIC_OVERRIDE);
+               break;
 
-               if (msleep_interruptible(500))
-                       break;
+       case ETHTOOL_ID_INACTIVE:
+               tw32(MAC_LED_CTRL, tp->led_ctrl);
+               break;
        }
-       tw32(MAC_LED_CTRL, tp->led_ctrl);
+
        return 0;
 }
 
@@ -10358,6 +10416,81 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
        memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
 }
 
+static __be32 * tg3_vpd_readblock(struct tg3 *tp)
+{
+       int i;
+       __be32 *buf;
+       u32 offset = 0, len = 0;
+       u32 magic, val;
+
+       if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
+           tg3_nvram_read(tp, 0, &magic))
+               return NULL;
+
+       if (magic == TG3_EEPROM_MAGIC) {
+               for (offset = TG3_NVM_DIR_START;
+                    offset < TG3_NVM_DIR_END;
+                    offset += TG3_NVM_DIRENT_SIZE) {
+                       if (tg3_nvram_read(tp, offset, &val))
+                               return NULL;
+
+                       if ((val >> TG3_NVM_DIRTYPE_SHIFT) ==
+                           TG3_NVM_DIRTYPE_EXTVPD)
+                               break;
+               }
+
+               if (offset != TG3_NVM_DIR_END) {
+                       len = (val & TG3_NVM_DIRTYPE_LENMSK) * 4;
+                       if (tg3_nvram_read(tp, offset + 4, &offset))
+                               return NULL;
+
+                       offset = tg3_nvram_logical_addr(tp, offset);
+               }
+       }
+
+       if (!offset || !len) {
+               offset = TG3_NVM_VPD_OFF;
+               len = TG3_NVM_VPD_LEN;
+       }
+
+       buf = kmalloc(len, GFP_KERNEL);
+       if (buf == NULL)
+               return NULL;
+
+       if (magic == TG3_EEPROM_MAGIC) {
+               for (i = 0; i < len; i += 4) {
+                       /* The data is in little-endian format in NVRAM.
+                        * Use the big-endian read routines to preserve
+                        * the byte order as it exists in NVRAM.
+                        */
+                       if (tg3_nvram_read_be32(tp, offset + i, &buf[i/4]))
+                               goto error;
+               }
+       } else {
+               u8 *ptr;
+               ssize_t cnt;
+               unsigned int pos = 0;
+
+               ptr = (u8 *)&buf[0];
+               for (i = 0; pos < len && i < 3; i++, pos += cnt, ptr += cnt) {
+                       cnt = pci_read_vpd(tp->pdev, pos,
+                                          len - pos, ptr);
+                       if (cnt == -ETIMEDOUT || cnt == -EINTR)
+                               cnt = 0;
+                       else if (cnt < 0)
+                               goto error;
+               }
+               if (pos != len)
+                       goto error;
+       }
+
+       return buf;
+
+error:
+       kfree(buf);
+       return NULL;
+}
+
 #define NVRAM_TEST_SIZE 0x100
 #define NVRAM_SELFBOOT_FORMAT1_0_SIZE  0x14
 #define NVRAM_SELFBOOT_FORMAT1_2_SIZE  0x18
@@ -10497,14 +10630,11 @@ static int tg3_test_nvram(struct tg3 *tp)
        if (csum != le32_to_cpu(buf[0xfc/4]))
                goto out;
 
-       for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
-               /* The data is in little-endian format in NVRAM.
-                * Use the big-endian read routines to preserve
-                * the byte order as it exists in NVRAM.
-                */
-               if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &buf[i/4]))
-                       goto out;
-       }
+       kfree(buf);
+
+       buf = tg3_vpd_readblock(tp);
+       if (!buf)
+               return -ENOMEM;
 
        i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN,
                             PCI_VPD_LRDT_RO_DATA);
@@ -10877,7 +11007,7 @@ static int tg3_test_memory(struct tg3 *tp)
 #define TG3_MAC_LOOPBACK       0
 #define TG3_PHY_LOOPBACK       1
 
-static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
+static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
 {
        u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
        u32 desc_idx, coal_now;
@@ -10975,7 +11105,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
        err = -EIO;
 
-       tx_len = 1514;
+       tx_len = pktsz;
        skb = netdev_alloc_skb(tp->dev, tx_len);
        if (!skb)
                return -ENOMEM;
@@ -10984,7 +11114,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        memcpy(tx_data, tp->dev->dev_addr, 6);
        memset(tx_data + 6, 0x0, 8);
 
-       tw32(MAC_RX_MTU_SIZE, tx_len + 4);
+       tw32(MAC_RX_MTU_SIZE, tx_len + ETH_FCS_LEN);
 
        for (i = 14; i < tx_len; i++)
                tx_data[i] = (u8) (i & 0xff);
@@ -11040,8 +11170,6 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        desc = &rnapi->rx_rcb[rx_start_idx];
        desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
        opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
-       if (opaque_key != RXD_OPAQUE_RING_STD)
-               goto out;
 
        if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
            (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII))
@@ -11051,9 +11179,20 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        if (rx_len != tx_len)
                goto out;
 
-       rx_skb = tpr->rx_std_buffers[desc_idx].skb;
+       if (pktsz <= TG3_RX_STD_DMA_SZ - ETH_FCS_LEN) {
+               if (opaque_key != RXD_OPAQUE_RING_STD)
+                       goto out;
+
+               rx_skb = tpr->rx_std_buffers[desc_idx].skb;
+               map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], mapping);
+       } else {
+               if (opaque_key != RXD_OPAQUE_RING_JUMBO)
+                       goto out;
+
+               rx_skb = tpr->rx_jmb_buffers[desc_idx].skb;
+               map = dma_unmap_addr(&tpr->rx_jmb_buffers[desc_idx], mapping);
+       }
 
-       map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], mapping);
        pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE);
 
        for (i = 14; i < tx_len; i++) {
@@ -11119,9 +11258,13 @@ static int tg3_test_loopback(struct tg3 *tp)
                                  CPMU_CTRL_LINK_AWARE_MODE));
        }
 
-       if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
+       if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_MAC_LOOPBACK))
                err |= TG3_MAC_LOOPBACK_FAILED;
 
+       if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) &&
+           tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_MAC_LOOPBACK))
+               err |= (TG3_MAC_LOOPBACK_FAILED << 2);
+
        if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
                tw32(TG3_CPMU_CTRL, cpmuctrl);
 
@@ -11131,8 +11274,11 @@ static int tg3_test_loopback(struct tg3 *tp)
 
        if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
            !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
-               if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
+               if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK))
                        err |= TG3_PHY_LOOPBACK_FAILED;
+               if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) &&
+                   tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK))
+                       err |= (TG3_PHY_LOOPBACK_FAILED << 2);
        }
 
        /* Re-enable gphy autopowerdown. */
@@ -11365,14 +11511,9 @@ static const struct ethtool_ops tg3_ethtool_ops = {
        .set_ringparam          = tg3_set_ringparam,
        .get_pauseparam         = tg3_get_pauseparam,
        .set_pauseparam         = tg3_set_pauseparam,
-       .get_rx_csum            = tg3_get_rx_csum,
-       .set_rx_csum            = tg3_set_rx_csum,
-       .set_tx_csum            = tg3_set_tx_csum,
-       .set_sg                 = ethtool_op_set_sg,
-       .set_tso                = tg3_set_tso,
        .self_test              = tg3_self_test,
        .get_strings            = tg3_get_strings,
-       .phys_id                = tg3_phys_id,
+       .set_phys_id            = tg3_set_phys_id,
        .get_ethtool_stats      = tg3_get_ethtool_stats,
        .get_coalesce           = tg3_get_coalesce,
        .set_coalesce           = tg3_set_coalesce,
@@ -11844,6 +11985,8 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
 
                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;
@@ -11869,8 +12012,10 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
 
                switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
                case FLASH_5717VENDOR_ST_M_M25PE20:
-               case FLASH_5717VENDOR_ST_A_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;
@@ -11889,6 +12034,118 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
                tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
 }
 
+static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1, nvmpinstrp;
+
+       nvcfg1 = tr32(NVRAM_CFG1);
+       nvmpinstrp = nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK;
+
+       switch (nvmpinstrp) {
+       case FLASH_5720_EEPROM_HD:
+       case FLASH_5720_EEPROM_LD:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->tg3_flags |= TG3_FLAG_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:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->tg3_flags2 |= TG3_FLG2_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:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->tg3_flags2 |= TG3_FLG2_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:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM;
+               return;
+       }
+
+       tg3_nvram_get_pagesize(tp, nvcfg1);
+       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
@@ -11933,8 +12190,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
                         GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                        tg3_get_57780_nvram_info(tp);
-               else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
+               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);
 
@@ -12717,46 +12977,11 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
        u8 *vpd_data;
        unsigned int block_end, rosize, len;
        int j, i = 0;
-       u32 magic;
 
-       if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
-           tg3_nvram_read(tp, 0x0, &magic))
-               goto out_no_vpd;
-
-       vpd_data = kmalloc(TG3_NVM_VPD_LEN, GFP_KERNEL);
+       vpd_data = (u8 *)tg3_vpd_readblock(tp);
        if (!vpd_data)
                goto out_no_vpd;
 
-       if (magic == TG3_EEPROM_MAGIC) {
-               for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
-                       u32 tmp;
-
-                       /* The data is in little-endian format in NVRAM.
-                        * Use the big-endian read routines to preserve
-                        * the byte order as it exists in NVRAM.
-                        */
-                       if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &tmp))
-                               goto out_not_found;
-
-                       memcpy(&vpd_data[i], &tmp, sizeof(tmp));
-               }
-       } else {
-               ssize_t cnt;
-               unsigned int pos = 0;
-
-               for (; pos < TG3_NVM_VPD_LEN && i < 3; i++, pos += cnt) {
-                       cnt = pci_read_vpd(tp->pdev, pos,
-                                          TG3_NVM_VPD_LEN - pos,
-                                          &vpd_data[pos]);
-                       if (cnt == -ETIMEDOUT || cnt == -EINTR)
-                               cnt = 0;
-                       else if (cnt < 0)
-                               goto out_not_found;
-               }
-               if (pos != TG3_NVM_VPD_LEN)
-                       goto out_not_found;
-       }
-
        i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN,
                             PCI_VPD_LRDT_RO_DATA);
        if (i < 0)
@@ -13118,11 +13343,6 @@ done:
 
 static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
 
-static inline void vlan_features_add(struct net_device *dev, unsigned long flags)
-{
-       dev->vlan_features |= flags;
-}
-
 static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
 {
        if (tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP)
@@ -13369,16 +13589,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        /* 5700 B0 chips do not support checksumming correctly due
         * to hardware bugs.
         */
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
-               tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
-       else {
-               unsigned long features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_GRO;
+       if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) {
+               u32 features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
 
-               tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
                if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
                        features |= NETIF_F_IPV6_CSUM;
                tp->dev->features |= features;
-               vlan_features_add(tp->dev, features);
+               tp->dev->hw_features |= features;
+               tp->dev->vlan_features |= features;
        }
 
        /* Determine TSO capabilities */
@@ -13765,7 +13983,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        /* Initialize data/descriptor byte/word swapping. */
        val = tr32(GRC_MODE);
-       val &= GRC_MODE_HOST_STACKUP;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               val &= (GRC_MODE_BYTE_SWAP_B2HRX_DATA |
+                       GRC_MODE_WORD_SWAP_B2HRX_DATA |
+                       GRC_MODE_B2HRX_ENABLE |
+                       GRC_MODE_HTX2B_ENABLE |
+                       GRC_MODE_HOST_STACKUP);
+       else
+               val &= GRC_MODE_HOST_STACKUP;
+
        tw32(GRC_MODE, val | tp->grc_mode);
 
        tg3_switch_clocks(tp);
@@ -14529,6 +14755,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case TG3_PHY_ID_BCM5718S:       return "5718S";
        case TG3_PHY_ID_BCM57765:       return "57765";
        case TG3_PHY_ID_BCM5719C:       return "5719C";
+       case TG3_PHY_ID_BCM5720C:       return "5720C";
        case TG3_PHY_ID_BCM8002:        return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
@@ -14641,6 +14868,7 @@ static const struct net_device_ops tg3_netdev_ops = {
        .ndo_do_ioctl           = tg3_ioctl,
        .ndo_tx_timeout         = tg3_tx_timeout,
        .ndo_change_mtu         = tg3_change_mtu,
+       .ndo_fix_features       = tg3_fix_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = tg3_poll_controller,
 #endif
@@ -14671,6 +14899,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        u32 sndmbx, rcvmbx, intmbx;
        char str[40];
        u64 dma_mask, persist_dma_mask;
+       u32 hw_features = 0;
 
        printk_once(KERN_INFO "%s\n", version);
 
@@ -14831,27 +15060,25 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         * is off by default, but can be enabled using ethtool.
         */
        if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) &&
-           (dev->features & NETIF_F_IP_CSUM)) {
-               dev->features |= NETIF_F_TSO;
-               vlan_features_add(dev, NETIF_F_TSO);
-       }
+           (dev->features & NETIF_F_IP_CSUM))
+               hw_features |= NETIF_F_TSO;
        if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
            (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3)) {
-               if (dev->features & NETIF_F_IPV6_CSUM) {
-                       dev->features |= NETIF_F_TSO6;
-                       vlan_features_add(dev, NETIF_F_TSO6);
-               }
+               if (dev->features & NETIF_F_IPV6_CSUM)
+                       hw_features |= NETIF_F_TSO6;
                if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
                    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
                     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
-                       dev->features |= NETIF_F_TSO_ECN;
-                       vlan_features_add(dev, NETIF_F_TSO_ECN);
-               }
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+                       hw_features |= NETIF_F_TSO_ECN;
        }
 
+       dev->hw_features |= hw_features;
+       dev->features |= hw_features;
+       dev->vlan_features |= hw_features;
+
        if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 &&
            !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) &&
            !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) {
@@ -14980,7 +15207,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        }
 
        netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n",
-                   (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
+                   (dev->features & NETIF_F_RXCSUM) != 0,
                    (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
                    (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) != 0,
                    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,