back ported tg3 / bnx2 NIC drivers
authorMarc Fiuczynski <mef@cs.princeton.edu>
Tue, 3 Apr 2007 06:05:57 +0000 (06:05 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Tue, 3 Apr 2007 06:05:57 +0000 (06:05 +0000)
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/tg3.c
drivers/net/tg3.h
include/linux/pci_ids.h

index a24200d..1fdb160 100644 (file)
@@ -9,20 +9,61 @@
  * Written by: Michael Chan  (mchan@broadcom.com)
  */
 
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/time.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#ifdef NETIF_F_HW_VLAN_TX
+#include <linux/if_vlan.h>
+#define BCM_VLAN 1
+#endif
+#ifdef NETIF_F_TSO
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/checksum.h>
+#define BCM_TSO 1
+#endif
+#include <linux/workqueue.h>
+#include <linux/crc32.h>
+#include <linux/prefetch.h>
+#include <linux/cache.h>
+
 #include "bnx2.h"
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.4.31"
-#define DRV_MODULE_RELDATE     "January 19, 2006"
+#define DRV_MODULE_VERSION     "1.4.40"
+#define DRV_MODULE_RELDATE     "May 22, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
        "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
@@ -46,7 +87,7 @@ typedef enum {
 } board_t;
 
 /* indexed by board_t, above */
-static struct {
+static const struct {
        char *name;
 } board_info[] __devinitdata = {
        { "Broadcom NetXtreme II BCM5706 1000Base-T" },
@@ -313,8 +354,6 @@ bnx2_disable_int(struct bnx2 *bp)
 static void
 bnx2_enable_int(struct bnx2 *bp)
 {
-       u32 val;
-
        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
               BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx);
@@ -322,8 +361,7 @@ bnx2_enable_int(struct bnx2 *bp)
        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
 
-       val = REG_RD(bp, BNX2_HC_COMMAND);
-       REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+       REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
 }
 
 static void
@@ -360,15 +398,13 @@ bnx2_netif_start(struct bnx2 *bp)
 static void
 bnx2_free_mem(struct bnx2 *bp)
 {
-       if (bp->stats_blk) {
-               pci_free_consistent(bp->pdev, sizeof(struct statistics_block),
-                                   bp->stats_blk, bp->stats_blk_mapping);
-               bp->stats_blk = NULL;
-       }
+       int i;
+
        if (bp->status_blk) {
-               pci_free_consistent(bp->pdev, sizeof(struct status_block),
+               pci_free_consistent(bp->pdev, bp->status_stats_size,
                                    bp->status_blk, bp->status_blk_mapping);
                bp->status_blk = NULL;
+               bp->stats_blk = NULL;
        }
        if (bp->tx_desc_ring) {
                pci_free_consistent(bp->pdev,
@@ -378,25 +414,28 @@ bnx2_free_mem(struct bnx2 *bp)
        }
        kfree(bp->tx_buf_ring);
        bp->tx_buf_ring = NULL;
-       if (bp->rx_desc_ring) {
-               pci_free_consistent(bp->pdev,
-                                   sizeof(struct rx_bd) * RX_DESC_CNT,
-                                   bp->rx_desc_ring, bp->rx_desc_mapping);
-               bp->rx_desc_ring = NULL;
-       }
-       kfree(bp->rx_buf_ring);
+       for (i = 0; i < bp->rx_max_ring; i++) {
+               if (bp->rx_desc_ring[i])
+                       pci_free_consistent(bp->pdev,
+                                           sizeof(struct rx_bd) * RX_DESC_CNT,
+                                           bp->rx_desc_ring[i],
+                                           bp->rx_desc_mapping[i]);
+               bp->rx_desc_ring[i] = NULL;
+       }
+       vfree(bp->rx_buf_ring);
        bp->rx_buf_ring = NULL;
 }
 
 static int
 bnx2_alloc_mem(struct bnx2 *bp)
 {
-       bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
-                                    GFP_KERNEL);
+       int i, status_blk_size;
+
+       bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
+                                 GFP_KERNEL);
        if (bp->tx_buf_ring == NULL)
                return -ENOMEM;
 
-       memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT);
        bp->tx_desc_ring = pci_alloc_consistent(bp->pdev,
                                                sizeof(struct tx_bd) *
                                                TX_DESC_CNT,
@@ -404,34 +443,40 @@ bnx2_alloc_mem(struct bnx2 *bp)
        if (bp->tx_desc_ring == NULL)
                goto alloc_mem_err;
 
-       bp->rx_buf_ring = kmalloc(sizeof(struct sw_bd) * RX_DESC_CNT,
-                                    GFP_KERNEL);
+       bp->rx_buf_ring = vmalloc(sizeof(struct sw_bd) * RX_DESC_CNT *
+                                 bp->rx_max_ring);
        if (bp->rx_buf_ring == NULL)
                goto alloc_mem_err;
 
-       memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT);
-       bp->rx_desc_ring = pci_alloc_consistent(bp->pdev,
-                                               sizeof(struct rx_bd) *
-                                               RX_DESC_CNT,
-                                               &bp->rx_desc_mapping);
-       if (bp->rx_desc_ring == NULL)
-               goto alloc_mem_err;
+       memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT *
+                                  bp->rx_max_ring);
+
+       for (i = 0; i < bp->rx_max_ring; i++) {
+               bp->rx_desc_ring[i] =
+                       pci_alloc_consistent(bp->pdev,
+                                            sizeof(struct rx_bd) * RX_DESC_CNT,
+                                            &bp->rx_desc_mapping[i]);
+               if (bp->rx_desc_ring[i] == NULL)
+                       goto alloc_mem_err;
+
+       }
 
-       bp->status_blk = pci_alloc_consistent(bp->pdev,
-                                             sizeof(struct status_block),
+       /* Combine status and statistics blocks into one allocation. */
+       status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
+       bp->status_stats_size = status_blk_size +
+                               sizeof(struct statistics_block);
+
+       bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size,
                                              &bp->status_blk_mapping);
        if (bp->status_blk == NULL)
                goto alloc_mem_err;
 
-       memset(bp->status_blk, 0, sizeof(struct status_block));
+       memset(bp->status_blk, 0, bp->status_stats_size);
 
-       bp->stats_blk = pci_alloc_consistent(bp->pdev,
-                                            sizeof(struct statistics_block),
-                                            &bp->stats_blk_mapping);
-       if (bp->stats_blk == NULL)
-               goto alloc_mem_err;
+       bp->stats_blk = (void *) ((unsigned long) bp->status_blk +
+                                 status_blk_size);
 
-       memset(bp->stats_blk, 0, sizeof(struct statistics_block));
+       bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
 
        return 0;
 
@@ -1520,7 +1565,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
        struct sk_buff *skb;
        struct sw_bd *rx_buf = &bp->rx_buf_ring[index];
        dma_addr_t mapping;
-       struct rx_bd *rxbd = &bp->rx_desc_ring[index];
+       struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
        unsigned long align;
 
        skb = dev_alloc_skb(bp->rx_buf_size);
@@ -1593,7 +1638,7 @@ bnx2_tx_int(struct bnx2 *bp)
                skb = tx_buf->skb;
 #ifdef BCM_TSO 
                /* partial BD completions possible with TSO packets */
-               if (skb_shinfo(skb)->tso_size) {
+               if (skb_shinfo(skb)->tso_size){
                        u16 last_idx, last_ring_idx;
 
                        last_idx = sw_cons +
@@ -1656,23 +1701,30 @@ static inline void
 bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
        u16 cons, u16 prod)
 {
-       struct sw_bd *cons_rx_buf = &bp->rx_buf_ring[cons];
-       struct sw_bd *prod_rx_buf = &bp->rx_buf_ring[prod];
-       struct rx_bd *cons_bd = &bp->rx_desc_ring[cons];
-       struct rx_bd *prod_bd = &bp->rx_desc_ring[prod];
+       struct sw_bd *cons_rx_buf, *prod_rx_buf;
+       struct rx_bd *cons_bd, *prod_bd;
+
+       cons_rx_buf = &bp->rx_buf_ring[cons];
+       prod_rx_buf = &bp->rx_buf_ring[prod];
 
        pci_dma_sync_single_for_device(bp->pdev,
                pci_unmap_addr(cons_rx_buf, mapping),
                bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
 
-       prod_rx_buf->skb = cons_rx_buf->skb;
-       pci_unmap_addr_set(prod_rx_buf, mapping,
-                       pci_unmap_addr(cons_rx_buf, mapping));
+       bp->rx_prod_bseq += bp->rx_buf_use_size;
 
-       memcpy(prod_bd, cons_bd, 8);
+       prod_rx_buf->skb = skb;
 
-       bp->rx_prod_bseq += bp->rx_buf_use_size;
+       if (cons == prod)
+               return;
+
+       pci_unmap_addr_set(prod_rx_buf, mapping,
+                       pci_unmap_addr(cons_rx_buf, mapping));
 
+       cons_bd = &bp->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
+       prod_bd = &bp->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+       prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
+       prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
 }
 
 static int
@@ -1699,14 +1751,19 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
                u32 status;
                struct sw_bd *rx_buf;
                struct sk_buff *skb;
+               dma_addr_t dma_addr;
 
                sw_ring_cons = RX_RING_IDX(sw_cons);
                sw_ring_prod = RX_RING_IDX(sw_prod);
 
                rx_buf = &bp->rx_buf_ring[sw_ring_cons];
                skb = rx_buf->skb;
-               pci_dma_sync_single_for_cpu(bp->pdev,
-                       pci_unmap_addr(rx_buf, mapping),
+
+               rx_buf->skb = NULL;
+
+               dma_addr = pci_unmap_addr(rx_buf, mapping);
+
+               pci_dma_sync_single_for_cpu(bp->pdev, dma_addr,
                        bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
 
                rx_hdr = (struct l2_fhdr *) skb->data;
@@ -1747,8 +1804,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
                        skb = new_skb;
                }
                else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) {
-                       pci_unmap_single(bp->pdev,
-                               pci_unmap_addr(rx_buf, mapping),
+                       pci_unmap_single(bp->pdev, dma_addr,
                                bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
 
                        skb_reserve(skb, bp->rx_offset);
@@ -1794,8 +1850,6 @@ reuse_rx:
                rx_pkt++;
 
 next_rx:
-               rx_buf->skb = NULL;
-
                sw_cons = NEXT_RX_BD(sw_cons);
                sw_prod = NEXT_RX_BD(sw_prod);
 
@@ -1906,6 +1960,13 @@ bnx2_poll(struct net_device *dev, int *budget)
                spin_lock(&bp->phy_lock);
                bnx2_phy_int(bp);
                spin_unlock(&bp->phy_lock);
+
+               /* This is needed to take care of transient status
+                * during link changes.
+                */
+               REG_WR(bp, BNX2_HC_COMMAND,
+                      bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+               REG_RD(bp, BNX2_HC_COMMAND);
        }
 
        if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
@@ -1948,7 +2009,7 @@ bnx2_poll(struct net_device *dev, int *budget)
        return 1;
 }
 
-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
+/* Called with rtnl_lock from vlan functions and also netif_tx_lock
  * from set_multicast.
  */
 static void
@@ -2884,7 +2945,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
                int buf_size)
 {
        u32 written, offset32, len32;
-       u8 *buf, start[4], end[4];
+       u8 *buf, start[4], end[4], *flash_buffer = NULL;
        int rc = 0;
        int align_start, align_end;
 
@@ -2924,12 +2985,19 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
                memcpy(buf + align_start, data_buf, buf_size);
        }
 
+       if (bp->flash_info->buffered == 0) {
+               flash_buffer = kmalloc(264, GFP_KERNEL);
+               if (flash_buffer == NULL) {
+                       rc = -ENOMEM;
+                       goto nvram_write_end;
+               }
+       }
+
        written = 0;
        while ((written < len32) && (rc == 0)) {
                u32 page_start, page_end, data_start, data_end;
                u32 addr, cmd_flags;
                int i;
-               u8 flash_buffer[264];
 
                /* Find the page_start addr */
                page_start = offset32 + written;
@@ -3000,7 +3068,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
                }
 
                /* Loop to write the new data from data_start to data_end */
-               for (addr = data_start; addr < data_end; addr += 4, i++) {
+               for (addr = data_start; addr < data_end; addr += 4, i += 4) {
                        if ((addr == page_end - 4) ||
                                ((bp->flash_info->buffered) &&
                                 (addr == data_end - 4))) {
@@ -3048,6 +3116,9 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
        }
 
 nvram_write_end:
+       if (bp->flash_info->buffered == 0)
+               kfree(flash_buffer);
+
        if (align_start || align_end)
                kfree(buf);
        return rc;
@@ -3287,6 +3358,8 @@ bnx2_init_chip(struct bnx2 *bp)
 
        udelay(20);
 
+       bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+
        return rc;
 }
 
@@ -3340,27 +3413,35 @@ bnx2_init_rx_ring(struct bnx2 *bp)
        bp->hw_rx_cons = 0;
        bp->rx_prod_bseq = 0;
                
-       rxbd = &bp->rx_desc_ring[0];
-       for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
-               rxbd->rx_bd_len = bp->rx_buf_use_size;
-               rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
-       }
+       for (i = 0; i < bp->rx_max_ring; i++) {
+               int j;
 
-       rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping >> 32;
-       rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff;
+               rxbd = &bp->rx_desc_ring[i][0];
+               for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
+                       rxbd->rx_bd_len = bp->rx_buf_use_size;
+                       rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
+               }
+               if (i == (bp->rx_max_ring - 1))
+                       j = 0;
+               else
+                       j = i + 1;
+               rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping[j] >> 32;
+               rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping[j] &
+                                      0xffffffff;
+       }
 
        val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
        val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
        val |= 0x02 << 8;
        CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
 
-       val = (u64) bp->rx_desc_mapping >> 32;
+       val = (u64) bp->rx_desc_mapping[0] >> 32;
        CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val);
 
-       val = (u64) bp->rx_desc_mapping & 0xffffffff;
+       val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
        CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
 
-       for ( ;ring_prod < bp->rx_ring_size; ) {
+       for (i = 0; i < bp->rx_ring_size; i++) {
                if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
                        break;
                }
@@ -3374,6 +3455,29 @@ bnx2_init_rx_ring(struct bnx2 *bp)
        REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
 }
 
+static void
+bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
+{
+       u32 num_rings, max;
+
+       bp->rx_ring_size = size;
+       num_rings = 1;
+       while (size > MAX_RX_DESC_CNT) {
+               size -= MAX_RX_DESC_CNT;
+               num_rings++;
+       }
+       /* round to next power of 2 */
+       max = MAX_RX_RINGS;
+       while ((max & num_rings) == 0)
+               max >>= 1;
+
+       if (num_rings != max)
+               max <<= 1;
+
+       bp->rx_max_ring = max;
+       bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
+}
+
 static void
 bnx2_free_tx_skbs(struct bnx2 *bp)
 {
@@ -3419,7 +3523,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
        if (bp->rx_buf_ring == NULL)
                return;
 
-       for (i = 0; i < RX_DESC_CNT; i++) {
+       for (i = 0; i < bp->rx_max_ring_idx; i++) {
                struct sw_bd *rx_buf = &bp->rx_buf_ring[i];
                struct sk_buff *skb = rx_buf->skb;
 
@@ -3476,7 +3580,7 @@ bnx2_test_registers(struct bnx2 *bp)
 {
        int ret;
        int i;
-       static struct {
+       static const struct {
                u16   offset;
                u16   flags;
                u32   rw_mask;
@@ -3506,74 +3610,9 @@ bnx2_test_registers(struct bnx2 *bp)
                { 0x0c00, 0, 0x00000000, 0x00000001 },
                { 0x0c04, 0, 0x00000000, 0x03ff0001 },
                { 0x0c08, 0, 0x0f0ff073, 0x00000000 },
-               { 0x0c0c, 0, 0x00ffffff, 0x00000000 },
-               { 0x0c30, 0, 0x00000000, 0xffffffff },
-               { 0x0c34, 0, 0x00000000, 0xffffffff },
-               { 0x0c38, 0, 0x00000000, 0xffffffff },
-               { 0x0c3c, 0, 0x00000000, 0xffffffff },
-               { 0x0c40, 0, 0x00000000, 0xffffffff },
-               { 0x0c44, 0, 0x00000000, 0xffffffff },
-               { 0x0c48, 0, 0x00000000, 0x0007ffff },
-               { 0x0c4c, 0, 0x00000000, 0xffffffff },
-               { 0x0c50, 0, 0x00000000, 0xffffffff },
-               { 0x0c54, 0, 0x00000000, 0xffffffff },
-               { 0x0c58, 0, 0x00000000, 0xffffffff },
-               { 0x0c5c, 0, 0x00000000, 0xffffffff },
-               { 0x0c60, 0, 0x00000000, 0xffffffff },
-               { 0x0c64, 0, 0x00000000, 0xffffffff },
-               { 0x0c68, 0, 0x00000000, 0xffffffff },
-               { 0x0c6c, 0, 0x00000000, 0xffffffff },
-               { 0x0c70, 0, 0x00000000, 0xffffffff },
-               { 0x0c74, 0, 0x00000000, 0xffffffff },
-               { 0x0c78, 0, 0x00000000, 0xffffffff },
-               { 0x0c7c, 0, 0x00000000, 0xffffffff },
-               { 0x0c80, 0, 0x00000000, 0xffffffff },
-               { 0x0c84, 0, 0x00000000, 0xffffffff },
-               { 0x0c88, 0, 0x00000000, 0xffffffff },
-               { 0x0c8c, 0, 0x00000000, 0xffffffff },
-               { 0x0c90, 0, 0x00000000, 0xffffffff },
-               { 0x0c94, 0, 0x00000000, 0xffffffff },
-               { 0x0c98, 0, 0x00000000, 0xffffffff },
-               { 0x0c9c, 0, 0x00000000, 0xffffffff },
-               { 0x0ca0, 0, 0x00000000, 0xffffffff },
-               { 0x0ca4, 0, 0x00000000, 0xffffffff },
-               { 0x0ca8, 0, 0x00000000, 0x0007ffff },
-               { 0x0cac, 0, 0x00000000, 0xffffffff },
-               { 0x0cb0, 0, 0x00000000, 0xffffffff },
-               { 0x0cb4, 0, 0x00000000, 0xffffffff },
-               { 0x0cb8, 0, 0x00000000, 0xffffffff },
-               { 0x0cbc, 0, 0x00000000, 0xffffffff },
-               { 0x0cc0, 0, 0x00000000, 0xffffffff },
-               { 0x0cc4, 0, 0x00000000, 0xffffffff },
-               { 0x0cc8, 0, 0x00000000, 0xffffffff },
-               { 0x0ccc, 0, 0x00000000, 0xffffffff },
-               { 0x0cd0, 0, 0x00000000, 0xffffffff },
-               { 0x0cd4, 0, 0x00000000, 0xffffffff },
-               { 0x0cd8, 0, 0x00000000, 0xffffffff },
-               { 0x0cdc, 0, 0x00000000, 0xffffffff },
-               { 0x0ce0, 0, 0x00000000, 0xffffffff },
-               { 0x0ce4, 0, 0x00000000, 0xffffffff },
-               { 0x0ce8, 0, 0x00000000, 0xffffffff },
-               { 0x0cec, 0, 0x00000000, 0xffffffff },
-               { 0x0cf0, 0, 0x00000000, 0xffffffff },
-               { 0x0cf4, 0, 0x00000000, 0xffffffff },
-               { 0x0cf8, 0, 0x00000000, 0xffffffff },
-               { 0x0cfc, 0, 0x00000000, 0xffffffff },
-               { 0x0d00, 0, 0x00000000, 0xffffffff },
-               { 0x0d04, 0, 0x00000000, 0xffffffff },
 
                { 0x1000, 0, 0x00000000, 0x00000001 },
                { 0x1004, 0, 0x00000000, 0x000f0001 },
-               { 0x1044, 0, 0x00000000, 0xffc003ff },
-               { 0x1080, 0, 0x00000000, 0x0001ffff },
-               { 0x1084, 0, 0x00000000, 0xffffffff },
-               { 0x1088, 0, 0x00000000, 0xffffffff },
-               { 0x108c, 0, 0x00000000, 0xffffffff },
-               { 0x1090, 0, 0x00000000, 0xffffffff },
-               { 0x1094, 0, 0x00000000, 0xffffffff },
-               { 0x1098, 0, 0x00000000, 0xffffffff },
-               { 0x109c, 0, 0x00000000, 0xffffffff },
-               { 0x10a0, 0, 0x00000000, 0xffffffff },
 
                { 0x1408, 0, 0x01c00800, 0x00000000 },
                { 0x149c, 0, 0x8000ffff, 0x00000000 },
@@ -3585,111 +3624,9 @@ bnx2_test_registers(struct bnx2 *bp)
                { 0x14c4, 0, 0x00003fff, 0x00000000 },
                { 0x14cc, 0, 0x00000000, 0x00000001 },
                { 0x14d0, 0, 0xffffffff, 0x00000000 },
-               { 0x1500, 0, 0x00000000, 0xffffffff },
-               { 0x1504, 0, 0x00000000, 0xffffffff },
-               { 0x1508, 0, 0x00000000, 0xffffffff },
-               { 0x150c, 0, 0x00000000, 0xffffffff },
-               { 0x1510, 0, 0x00000000, 0xffffffff },
-               { 0x1514, 0, 0x00000000, 0xffffffff },
-               { 0x1518, 0, 0x00000000, 0xffffffff },
-               { 0x151c, 0, 0x00000000, 0xffffffff },
-               { 0x1520, 0, 0x00000000, 0xffffffff },
-               { 0x1524, 0, 0x00000000, 0xffffffff },
-               { 0x1528, 0, 0x00000000, 0xffffffff },
-               { 0x152c, 0, 0x00000000, 0xffffffff },
-               { 0x1530, 0, 0x00000000, 0xffffffff },
-               { 0x1534, 0, 0x00000000, 0xffffffff },
-               { 0x1538, 0, 0x00000000, 0xffffffff },
-               { 0x153c, 0, 0x00000000, 0xffffffff },
-               { 0x1540, 0, 0x00000000, 0xffffffff },
-               { 0x1544, 0, 0x00000000, 0xffffffff },
-               { 0x1548, 0, 0x00000000, 0xffffffff },
-               { 0x154c, 0, 0x00000000, 0xffffffff },
-               { 0x1550, 0, 0x00000000, 0xffffffff },
-               { 0x1554, 0, 0x00000000, 0xffffffff },
-               { 0x1558, 0, 0x00000000, 0xffffffff },
-               { 0x1600, 0, 0x00000000, 0xffffffff },
-               { 0x1604, 0, 0x00000000, 0xffffffff },
-               { 0x1608, 0, 0x00000000, 0xffffffff },
-               { 0x160c, 0, 0x00000000, 0xffffffff },
-               { 0x1610, 0, 0x00000000, 0xffffffff },
-               { 0x1614, 0, 0x00000000, 0xffffffff },
-               { 0x1618, 0, 0x00000000, 0xffffffff },
-               { 0x161c, 0, 0x00000000, 0xffffffff },
-               { 0x1620, 0, 0x00000000, 0xffffffff },
-               { 0x1624, 0, 0x00000000, 0xffffffff },
-               { 0x1628, 0, 0x00000000, 0xffffffff },
-               { 0x162c, 0, 0x00000000, 0xffffffff },
-               { 0x1630, 0, 0x00000000, 0xffffffff },
-               { 0x1634, 0, 0x00000000, 0xffffffff },
-               { 0x1638, 0, 0x00000000, 0xffffffff },
-               { 0x163c, 0, 0x00000000, 0xffffffff },
-               { 0x1640, 0, 0x00000000, 0xffffffff },
-               { 0x1644, 0, 0x00000000, 0xffffffff },
-               { 0x1648, 0, 0x00000000, 0xffffffff },
-               { 0x164c, 0, 0x00000000, 0xffffffff },
-               { 0x1650, 0, 0x00000000, 0xffffffff },
-               { 0x1654, 0, 0x00000000, 0xffffffff },
 
                { 0x1800, 0, 0x00000000, 0x00000001 },
                { 0x1804, 0, 0x00000000, 0x00000003 },
-               { 0x1840, 0, 0x00000000, 0xffffffff },
-               { 0x1844, 0, 0x00000000, 0xffffffff },
-               { 0x1848, 0, 0x00000000, 0xffffffff },
-               { 0x184c, 0, 0x00000000, 0xffffffff },
-               { 0x1850, 0, 0x00000000, 0xffffffff },
-               { 0x1900, 0, 0x7ffbffff, 0x00000000 },
-               { 0x1904, 0, 0xffffffff, 0x00000000 },
-               { 0x190c, 0, 0xffffffff, 0x00000000 },
-               { 0x1914, 0, 0xffffffff, 0x00000000 },
-               { 0x191c, 0, 0xffffffff, 0x00000000 },
-               { 0x1924, 0, 0xffffffff, 0x00000000 },
-               { 0x192c, 0, 0xffffffff, 0x00000000 },
-               { 0x1934, 0, 0xffffffff, 0x00000000 },
-               { 0x193c, 0, 0xffffffff, 0x00000000 },
-               { 0x1944, 0, 0xffffffff, 0x00000000 },
-               { 0x194c, 0, 0xffffffff, 0x00000000 },
-               { 0x1954, 0, 0xffffffff, 0x00000000 },
-               { 0x195c, 0, 0xffffffff, 0x00000000 },
-               { 0x1964, 0, 0xffffffff, 0x00000000 },
-               { 0x196c, 0, 0xffffffff, 0x00000000 },
-               { 0x1974, 0, 0xffffffff, 0x00000000 },
-               { 0x197c, 0, 0xffffffff, 0x00000000 },
-               { 0x1980, 0, 0x0700ffff, 0x00000000 },
-
-               { 0x1c00, 0, 0x00000000, 0x00000001 },
-               { 0x1c04, 0, 0x00000000, 0x00000003 },
-               { 0x1c08, 0, 0x0000000f, 0x00000000 },
-               { 0x1c40, 0, 0x00000000, 0xffffffff },
-               { 0x1c44, 0, 0x00000000, 0xffffffff },
-               { 0x1c48, 0, 0x00000000, 0xffffffff },
-               { 0x1c4c, 0, 0x00000000, 0xffffffff },
-               { 0x1c50, 0, 0x00000000, 0xffffffff },
-               { 0x1d00, 0, 0x7ffbffff, 0x00000000 },
-               { 0x1d04, 0, 0xffffffff, 0x00000000 },
-               { 0x1d0c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d14, 0, 0xffffffff, 0x00000000 },
-               { 0x1d1c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d24, 0, 0xffffffff, 0x00000000 },
-               { 0x1d2c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d34, 0, 0xffffffff, 0x00000000 },
-               { 0x1d3c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d44, 0, 0xffffffff, 0x00000000 },
-               { 0x1d4c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d54, 0, 0xffffffff, 0x00000000 },
-               { 0x1d5c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d64, 0, 0xffffffff, 0x00000000 },
-               { 0x1d6c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d74, 0, 0xffffffff, 0x00000000 },
-               { 0x1d7c, 0, 0xffffffff, 0x00000000 },
-               { 0x1d80, 0, 0x0700ffff, 0x00000000 },
-
-               { 0x2004, 0, 0x00000000, 0x0337000f },
-               { 0x2008, 0, 0xffffffff, 0x00000000 },
-               { 0x200c, 0, 0xffffffff, 0x00000000 },
-               { 0x2010, 0, 0xffffffff, 0x00000000 },
-               { 0x2014, 0, 0x801fff80, 0x00000000 },
-               { 0x2018, 0, 0x000003ff, 0x00000000 },
 
                { 0x2800, 0, 0x00000000, 0x00000001 },
                { 0x2804, 0, 0x00000000, 0x00003f01 },
@@ -3707,16 +3644,6 @@ bnx2_test_registers(struct bnx2 *bp)
                { 0x2c00, 0, 0x00000000, 0x00000011 },
                { 0x2c04, 0, 0x00000000, 0x00030007 },
 
-               { 0x3000, 0, 0x00000000, 0x00000001 },
-               { 0x3004, 0, 0x00000000, 0x007007ff },
-               { 0x3008, 0, 0x00000003, 0x00000000 },
-               { 0x300c, 0, 0xffffffff, 0x00000000 },
-               { 0x3010, 0, 0xffffffff, 0x00000000 },
-               { 0x3014, 0, 0xffffffff, 0x00000000 },
-               { 0x3034, 0, 0xffffffff, 0x00000000 },
-               { 0x3038, 0, 0xffffffff, 0x00000000 },
-               { 0x3050, 0, 0x00000001, 0x00000000 },
-
                { 0x3c00, 0, 0x00000000, 0x00000001 },
                { 0x3c04, 0, 0x00000000, 0x00070000 },
                { 0x3c08, 0, 0x00007f71, 0x07f00000 },
@@ -3726,88 +3653,11 @@ bnx2_test_registers(struct bnx2 *bp)
                { 0x3c18, 0, 0x00000000, 0xffffffff },
                { 0x3c1c, 0, 0xfffff000, 0x00000000 },
                { 0x3c20, 0, 0xffffff00, 0x00000000 },
-               { 0x3c24, 0, 0xffffffff, 0x00000000 },
-               { 0x3c28, 0, 0xffffffff, 0x00000000 },
-               { 0x3c2c, 0, 0xffffffff, 0x00000000 },
-               { 0x3c30, 0, 0xffffffff, 0x00000000 },
-               { 0x3c34, 0, 0xffffffff, 0x00000000 },
-               { 0x3c38, 0, 0xffffffff, 0x00000000 },
-               { 0x3c3c, 0, 0xffffffff, 0x00000000 },
-               { 0x3c40, 0, 0xffffffff, 0x00000000 },
-               { 0x3c44, 0, 0xffffffff, 0x00000000 },
-               { 0x3c48, 0, 0xffffffff, 0x00000000 },
-               { 0x3c4c, 0, 0xffffffff, 0x00000000 },
-               { 0x3c50, 0, 0xffffffff, 0x00000000 },
-               { 0x3c54, 0, 0xffffffff, 0x00000000 },
-               { 0x3c58, 0, 0xffffffff, 0x00000000 },
-               { 0x3c5c, 0, 0xffffffff, 0x00000000 },
-               { 0x3c60, 0, 0xffffffff, 0x00000000 },
-               { 0x3c64, 0, 0xffffffff, 0x00000000 },
-               { 0x3c68, 0, 0xffffffff, 0x00000000 },
-               { 0x3c6c, 0, 0xffffffff, 0x00000000 },
-               { 0x3c70, 0, 0xffffffff, 0x00000000 },
-               { 0x3c74, 0, 0x0000003f, 0x00000000 },
-               { 0x3c78, 0, 0x00000000, 0x00000000 },
-               { 0x3c7c, 0, 0x00000000, 0x00000000 },
-               { 0x3c80, 0, 0x3fffffff, 0x00000000 },
-               { 0x3c84, 0, 0x0000003f, 0x00000000 },
-               { 0x3c88, 0, 0x00000000, 0xffffffff },
-               { 0x3c8c, 0, 0x00000000, 0xffffffff },
-
-               { 0x4000, 0, 0x00000000, 0x00000001 },
-               { 0x4004, 0, 0x00000000, 0x00030000 },
-               { 0x4008, 0, 0x00000ff0, 0x00000000 },
-               { 0x400c, 0, 0xffffffff, 0x00000000 },
-               { 0x4088, 0, 0x00000000, 0x00070303 },
-
-               { 0x4400, 0, 0x00000000, 0x00000001 },
-               { 0x4404, 0, 0x00000000, 0x00003f01 },
-               { 0x4408, 0, 0x7fff00ff, 0x00000000 },
-               { 0x440c, 0, 0xffffffff, 0x00000000 },
-               { 0x4410, 0, 0xffff,     0x0000 },
-               { 0x4414, 0, 0xffff,     0x0000 },
-               { 0x4418, 0, 0xffff,     0x0000 },
-               { 0x441c, 0, 0xffff,     0x0000 },
-               { 0x4428, 0, 0xffffffff, 0x00000000 },
-               { 0x442c, 0, 0xffffffff, 0x00000000 },
-               { 0x4430, 0, 0xffffffff, 0x00000000 },
-               { 0x4434, 0, 0xffffffff, 0x00000000 },
-               { 0x4438, 0, 0xffffffff, 0x00000000 },
-               { 0x443c, 0, 0xffffffff, 0x00000000 },
-               { 0x4440, 0, 0xffffffff, 0x00000000 },
-               { 0x4444, 0, 0xffffffff, 0x00000000 },
-
-               { 0x4c00, 0, 0x00000000, 0x00000001 },
-               { 0x4c04, 0, 0x00000000, 0x0000003f },
-               { 0x4c08, 0, 0xffffffff, 0x00000000 },
-               { 0x4c0c, 0, 0x0007fc00, 0x00000000 },
-               { 0x4c10, 0, 0x80003fe0, 0x00000000 },
-               { 0x4c14, 0, 0xffffffff, 0x00000000 },
-               { 0x4c44, 0, 0x00000000, 0x9fff9fff },
-               { 0x4c48, 0, 0x00000000, 0xb3009fff },
-               { 0x4c4c, 0, 0x00000000, 0x77f33b30 },
-               { 0x4c50, 0, 0x00000000, 0xffffffff },
 
                { 0x5004, 0, 0x00000000, 0x0000007f },
                { 0x5008, 0, 0x0f0007ff, 0x00000000 },
                { 0x500c, 0, 0xf800f800, 0x07ff07ff },
 
-               { 0x5400, 0, 0x00000008, 0x00000001 },
-               { 0x5404, 0, 0x00000000, 0x0000003f },
-               { 0x5408, 0, 0x0000001f, 0x00000000 },
-               { 0x540c, 0, 0xffffffff, 0x00000000 },
-               { 0x5410, 0, 0xffffffff, 0x00000000 },
-               { 0x5414, 0, 0x0000ffff, 0x00000000 },
-               { 0x5418, 0, 0x0000ffff, 0x00000000 },
-               { 0x541c, 0, 0x0000ffff, 0x00000000 },
-               { 0x5420, 0, 0x0000ffff, 0x00000000 },
-               { 0x5428, 0, 0x000000ff, 0x00000000 },
-               { 0x542c, 0, 0xff00ffff, 0x00000000 },
-               { 0x5430, 0, 0x001fff80, 0x00000000 },
-               { 0x5438, 0, 0xffffffff, 0x00000000 },
-               { 0x543c, 0, 0xffffffff, 0x00000000 },
-               { 0x5440, 0, 0xf800f800, 0x07ff07ff },
-
                { 0x5c00, 0, 0x00000000, 0x00000001 },
                { 0x5c04, 0, 0x00000000, 0x0003000f },
                { 0x5c08, 0, 0x00000003, 0x00000000 },
@@ -3891,7 +3741,7 @@ reg_test_err:
 static int
 bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size)
 {
-       static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
+       static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
                0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa };
        int i;
 
@@ -3916,7 +3766,7 @@ bnx2_test_memory(struct bnx2 *bp)
 {
        int ret = 0;
        int i;
-       static struct {
+       static const struct {
                u32   offset;
                u32   len;
        } mem_tbl[] = {
@@ -3949,7 +3799,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
        struct sk_buff *skb, *rx_skb;
        unsigned char *packet;
        u16 rx_start_idx, rx_idx;
-       u32 val;
        dma_addr_t map;
        struct tx_bd *txbd;
        struct sw_bd *rx_buf;
@@ -3980,8 +3829,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
        map = pci_map_single(bp->pdev, skb->data, pkt_size,
                PCI_DMA_TODEVICE);
 
-       val = REG_RD(bp, BNX2_HC_COMMAND);
-       REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+       REG_WR(bp, BNX2_HC_COMMAND,
+              bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+
        REG_RD(bp, BNX2_HC_COMMAND);
 
        udelay(5);
@@ -4005,8 +3855,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 
        udelay(100);
 
-       val = REG_RD(bp, BNX2_HC_COMMAND);
-       REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+       REG_WR(bp, BNX2_HC_COMMAND,
+              bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+
        REG_RD(bp, BNX2_HC_COMMAND);
 
        udelay(5);
@@ -4142,7 +3993,6 @@ static int
 bnx2_test_intr(struct bnx2 *bp)
 {
        int i;
-       u32 val;
        u16 status_idx;
 
        if (!netif_running(bp->dev))
@@ -4151,8 +4001,7 @@ bnx2_test_intr(struct bnx2 *bp)
        status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
 
        /* This register is not touched during run-time. */
-       val = REG_RD(bp, BNX2_HC_COMMAND);
-       REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+       REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
        REG_RD(bp, BNX2_HC_COMMAND);
 
        for (i = 0; i < 10; i++) {
@@ -4403,7 +4252,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
 }
 #endif
 
-/* Called with dev->xmit_lock.
+/* Called with netif_tx_lock.
  * hard_start_xmit is pseudo-lockless - a lock is only required when
  * the tx queue is full. This way, we get the benefit of lockless
  * operations most of the time without the complexities to handle
@@ -4794,6 +4643,64 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        info->fw_version[5] = 0;
 }
 
+#define BNX2_REGDUMP_LEN               (32 * 1024)
+
+static int
+bnx2_get_regs_len(struct net_device *dev)
+{
+       return BNX2_REGDUMP_LEN;
+}
+
+static void
+bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
+{
+       u32 *p = _p, i, offset;
+       u8 *orig_p = _p;
+       struct bnx2 *bp = netdev_priv(dev);
+       u32 reg_boundaries[] = { 0x0000, 0x0098, 0x0400, 0x045c,
+                                0x0800, 0x0880, 0x0c00, 0x0c10,
+                                0x0c30, 0x0d08, 0x1000, 0x101c,
+                                0x1040, 0x1048, 0x1080, 0x10a4,
+                                0x1400, 0x1490, 0x1498, 0x14f0,
+                                0x1500, 0x155c, 0x1580, 0x15dc,
+                                0x1600, 0x1658, 0x1680, 0x16d8,
+                                0x1800, 0x1820, 0x1840, 0x1854,
+                                0x1880, 0x1894, 0x1900, 0x1984,
+                                0x1c00, 0x1c0c, 0x1c40, 0x1c54,
+                                0x1c80, 0x1c94, 0x1d00, 0x1d84,
+                                0x2000, 0x2030, 0x23c0, 0x2400,
+                                0x2800, 0x2820, 0x2830, 0x2850,
+                                0x2b40, 0x2c10, 0x2fc0, 0x3058,
+                                0x3c00, 0x3c94, 0x4000, 0x4010,
+                                0x4080, 0x4090, 0x43c0, 0x4458,
+                                0x4c00, 0x4c18, 0x4c40, 0x4c54,
+                                0x4fc0, 0x5010, 0x53c0, 0x5444,
+                                0x5c00, 0x5c18, 0x5c80, 0x5c90,
+                                0x5fc0, 0x6000, 0x6400, 0x6428,
+                                0x6800, 0x6848, 0x684c, 0x6860,
+                                0x6888, 0x6910, 0x8000 };
+
+       regs->version = 0;
+
+       memset(p, 0, BNX2_REGDUMP_LEN);
+
+       if (!netif_running(bp->dev))
+               return;
+
+       i = 0;
+       offset = reg_boundaries[0];
+       p += offset;
+       while (offset < BNX2_REGDUMP_LEN) {
+               *p++ = REG_RD(bp, offset);
+               offset += 4;
+               if (offset == reg_boundaries[i + 1]) {
+                       offset = reg_boundaries[i + 2];
+                       p = (u32 *) (orig_p + offset);
+                       i += 2;
+               }
+       }
+}
+
 static void
 bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
@@ -4979,7 +4886,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
        struct bnx2 *bp = netdev_priv(dev);
 
-       ering->rx_max_pending = MAX_RX_DESC_CNT;
+       ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
        ering->rx_mini_max_pending = 0;
        ering->rx_jumbo_max_pending = 0;
 
@@ -4996,17 +4903,28 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
        struct bnx2 *bp = netdev_priv(dev);
 
-       if ((ering->rx_pending > MAX_RX_DESC_CNT) ||
+       if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
                (ering->tx_pending > MAX_TX_DESC_CNT) ||
                (ering->tx_pending <= MAX_SKB_FRAGS)) {
 
                return -EINVAL;
        }
-       bp->rx_ring_size = ering->rx_pending;
+       if (netif_running(bp->dev)) {
+               bnx2_netif_stop(bp);
+               bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
+               bnx2_free_skbs(bp);
+               bnx2_free_mem(bp);
+       }
+
+       bnx2_set_rx_ring_size(bp, ering->rx_pending);
        bp->tx_ring_size = ering->tx_pending;
 
        if (netif_running(bp->dev)) {
-               bnx2_netif_stop(bp);
+               int rc;
+
+               rc = bnx2_alloc_mem(bp);
+               if (rc)
+                       return rc;
                bnx2_init_nic(bp);
                bnx2_netif_start(bp);
        }
@@ -5122,7 +5040,7 @@ static struct {
 
 #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
 
-static unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
+static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
     STATS_OFFSET32(stat_IfHCInOctets_hi),
     STATS_OFFSET32(stat_IfHCInBadOctets_hi),
     STATS_OFFSET32(stat_IfHCOutOctets_hi),
@@ -5360,6 +5278,8 @@ static struct ethtool_ops bnx2_ethtool_ops = {
        .get_settings           = bnx2_get_settings,
        .set_settings           = bnx2_set_settings,
        .get_drvinfo            = bnx2_get_drvinfo,
+       .get_regs_len           = bnx2_get_regs_len,
+       .get_regs               = bnx2_get_regs,
        .get_wol                = bnx2_get_wol,
        .set_wol                = bnx2_set_wol,
        .nway_reset             = bnx2_nway_reset,
@@ -5678,7 +5598,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->mac_addr[5] = (u8) reg;
 
        bp->tx_ring_size = MAX_TX_DESC_CNT;
-       bp->rx_ring_size = 100;
+       bnx2_set_rx_ring_size(bp, 100);
 
        bp->rx_csum = 1;
 
@@ -5897,6 +5817,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
        if (!netif_running(dev))
                return 0;
 
+       flush_scheduled_work();
        bnx2_netif_stop(bp);
        netif_device_detach(dev);
        del_timer_sync(&bp->timer);
index 9f691cb..b87925f 100644 (file)
 #ifndef BNX2_H
 #define BNX2_H
 
-#include <linux/config.h>
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/delay.h>
-#include <asm/byteorder.h>
-#include <linux/time.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#ifdef NETIF_F_HW_VLAN_TX
-#include <linux/if_vlan.h>
-#define BCM_VLAN 1
-#endif
-#ifdef NETIF_F_TSO
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <net/checksum.h>
-#define BCM_TSO 1
-#endif
-#include <linux/workqueue.h>
-#include <linux/crc32.h>
-#include <linux/prefetch.h>
-
 /* Hardware data structures and register definitions automatically
  * generated from RTL code. Do not modify.
  */
@@ -3792,8 +3753,10 @@ struct l2_fhdr {
 #define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
 #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
 
+#define MAX_RX_RINGS   4
 #define RX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct rx_bd))
 #define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
+#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
 
 #define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) ==                        \
                (MAX_TX_DESC_CNT - 1)) ?                                \
@@ -3805,8 +3768,10 @@ struct l2_fhdr {
                (MAX_RX_DESC_CNT - 1)) ?                                \
        (x) + 2 : (x) + 1
 
-#define RX_RING_IDX(x) ((x) & MAX_RX_DESC_CNT)
+#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
 
+#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
+#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
 
 /* Context size. */
 #define CTX_SHIFT                   7
@@ -3903,15 +3868,26 @@ struct bnx2 {
        struct status_block     *status_blk;
        u32                     last_status_idx;
 
-       struct tx_bd            *tx_desc_ring;
-       struct sw_bd            *tx_buf_ring;
-       u32                     tx_prod_bseq;
-       u16                     tx_prod;
-       u16                     tx_cons;
-       int                     tx_ring_size;
+       u32                     flags;
+#define PCIX_FLAG                      1
+#define PCI_32BIT_FLAG                 2
+#define ONE_TDMA_FLAG                  4       /* no longer used */
+#define NO_WOL_FLAG                    8
+#define USING_DAC_FLAG                 0x10
+#define USING_MSI_FLAG                 0x20
+#define ASF_ENABLE_FLAG                        0x40
 
-       u16                     hw_tx_cons;
-       u16                     hw_rx_cons;
+       /* Put tx producer and consumer fields in separate cache lines. */
+
+       u32             tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
+       u16             tx_prod;
+
+       struct tx_bd    *tx_desc_ring;
+       struct sw_bd    *tx_buf_ring;
+       int             tx_ring_size;
+
+       u16             tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
+       u16             hw_tx_cons;
 
 #ifdef BCM_VLAN 
        struct                  vlan_group *vlgrp;
@@ -3920,19 +3896,23 @@ struct bnx2 {
        u32                     rx_offset;
        u32                     rx_buf_use_size;        /* useable size */
        u32                     rx_buf_size;            /* with alignment */
-       struct rx_bd            *rx_desc_ring;
-       struct sw_bd            *rx_buf_ring;
+       u32                     rx_max_ring_idx;
+
        u32                     rx_prod_bseq;
        u16                     rx_prod;
        u16                     rx_cons;
+       u16                     hw_rx_cons;
 
        u32                     rx_csum;
 
+       struct sw_bd            *rx_buf_ring;
+       struct rx_bd            *rx_desc_ring[MAX_RX_RINGS];
+
        /* Only used to synchronize netif_stop_queue/wake_queue when tx */
        /* ring is full */
        spinlock_t              tx_lock;
 
-       /* End of fileds used in the performance code paths. */
+       /* End of fields used in the performance code paths. */
 
        char                    *name;
 
@@ -3945,15 +3925,6 @@ struct bnx2 {
        /* Used to synchronize phy accesses. */
        spinlock_t              phy_lock;
 
-       u32                     flags;
-#define PCIX_FLAG                      1
-#define PCI_32BIT_FLAG                 2
-#define ONE_TDMA_FLAG                  4       /* no longer used */
-#define NO_WOL_FLAG                    8
-#define USING_DAC_FLAG                 0x10
-#define USING_MSI_FLAG                 0x20
-#define ASF_ENABLE_FLAG                        0x40
-
        u32                     phy_flags;
 #define PHY_SERDES_FLAG                        1
 #define PHY_CRC_FIX_FLAG               2
@@ -4004,8 +3975,9 @@ struct bnx2 {
        dma_addr_t              tx_desc_mapping;
 
 
+       int                     rx_max_ring;
        int                     rx_ring_size;
-       dma_addr_t              rx_desc_mapping;
+       dma_addr_t              rx_desc_mapping[MAX_RX_RINGS];
 
        u16                     tx_quick_cons_trip;
        u16                     tx_quick_cons_trip_int;
@@ -4029,6 +4001,7 @@ struct bnx2 {
        struct statistics_block *stats_blk;
        dma_addr_t              stats_blk_mapping;
 
+       u32                     hc_cmd;
        u32                     rx_mode;
 
        u16                     req_line_speed;
@@ -4073,6 +4046,8 @@ struct bnx2 {
 
        struct flash_spec       *flash_info;
        u32                     flash_size;
+
+       int                     status_stats_size;
 };
 
 static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
index 6d63836..38b605d 100644 (file)
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.49"
-#define DRV_MODULE_RELDATE     "Feb 2, 2006"
+#define DRV_MODULE_VERSION     "3.59.1"
+#define DRV_MODULE_RELDATE     "August 25, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -221,10 +221,26 @@ static struct pci_device_id tg3_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S,
@@ -481,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
        unsigned long flags;
 
        spin_lock_irqsave(&tp->indirect_lock, flags);
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+       if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
-       /* Always leave this as zero. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-       spin_unlock_irqrestore(&tp->indirect_lock, flags);
-}
+               /* Always leave this as zero. */
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       } else {
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+               tw32_f(TG3PCI_MEM_WIN_DATA, val);
 
-static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
-{
-       /* If no workaround is needed, write to mem space directly */
-       if (tp->write32 != tg3_write_indirect_reg32)
-               tw32(NIC_SRAM_WIN_BASE + off, val);
-       else
-               tg3_write_mem(tp, off, val);
+               /* Always leave this as zero. */
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       }
+       spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
 static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
@@ -503,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
        unsigned long flags;
 
        spin_lock_irqsave(&tp->indirect_lock, flags);
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-       pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+       if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+               pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
-       /* Always leave this as zero. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+               /* Always leave this as zero. */
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       } else {
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+               *val = tr32(TG3PCI_MEM_WIN_DATA);
+
+               /* Always leave this as zero. */
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       }
        spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
@@ -534,6 +557,9 @@ static void tg3_enable_ints(struct tg3 *tp)
             (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
        tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
                       (tp->last_tag << 24));
+       if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
+               tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+                              (tp->last_tag << 24));
        tg3_cond_int(tp);
 }
 
@@ -948,6 +974,8 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
        return err;
 }
 
+static void tg3_link_report(struct tg3 *);
+
 /* This will reset the tigon3 PHY if there is no valid
  * link unless the FORCE argument is non-zero.
  */
@@ -961,6 +989,11 @@ static int tg3_phy_reset(struct tg3 *tp)
        if (err != 0)
                return -EBUSY;
 
+       if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
+               netif_carrier_off(tp->dev);
+               tg3_link_report(tp);
+       }
+
        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) {
@@ -997,6 +1030,12 @@ out:
                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2);
                tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
        }
+       else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) {
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+       }
        /* Set Extended packet length bit (bit 14) on all chips that */
        /* support jumbo frames */
        if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
@@ -1038,9 +1077,11 @@ static void tg3_frob_aux_power(struct tg3 *tp)
                struct net_device *dev_peer;
 
                dev_peer = pci_get_drvdata(tp->pdev_peer);
+               /* remove_one() may have been run on the peer. */
                if (!dev_peer)
-                       BUG();
-               tp_peer = netdev_priv(dev_peer);
+                       tp_peer = tp;
+               else
+                       tp_peer = netdev_priv(dev_peer);
        }
 
        if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
@@ -1131,7 +1172,20 @@ static int tg3_halt_cpu(struct tg3 *, u32);
 static int tg3_nvram_lock(struct tg3 *);
 static void tg3_nvram_unlock(struct tg3 *);
 
-static int tg3_set_power_state(struct tg3 *tp, int state)
+static void tg3_power_down_phy(struct tg3 *tp)
+{
+       /* The PHY should not be powered down on some chips because
+        * of bugs.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
+            (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
+               return;
+       tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
+}
+
+static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
 {
        u32 misc_host_ctrl;
        u16 power_control, power_caps;
@@ -1150,7 +1204,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
        power_control |= PCI_PM_CTRL_PME_STATUS;
        power_control &= ~(PCI_PM_CTRL_STATE_MASK);
        switch (state) {
-       case 0:
+       case PCI_D0:
                power_control |= 0;
                pci_write_config_word(tp->pdev,
                                      pm + PCI_PM_CTRL,
@@ -1163,15 +1217,15 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
 
                return 0;
 
-       case 1:
+       case PCI_D1:
                power_control |= 1;
                break;
 
-       case 2:
+       case PCI_D2:
                power_control |= 2;
                break;
 
-       case 3:
+       case PCI_D3hot:
                power_control |= 3;
                break;
 
@@ -1310,8 +1364,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
                        tg3_writephy(tp, MII_TG3_EXT_CTRL,
                                     MII_TG3_EXT_CTRL_FORCE_LED_OFF);
                        tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
-                               tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
+                       tg3_power_down_phy(tp);
                }
        }
 
@@ -1334,12 +1387,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
                }
        }
 
+       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
        /* Finally, set the new power state. */
        pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
        udelay(100);    /* Delay after power state change */
 
-       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
        return 0;
 }
 
@@ -2680,6 +2733,12 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
 
        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+               if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
+                       bmsr |= BMSR_LSTATUS;
+               else
+                       bmsr &= ~BMSR_LSTATUS;
+       }
 
        err |= tg3_readphy(tp, MII_BMCR, &bmcr);
 
@@ -2748,6 +2807,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                        bmcr = new_bmcr;
                        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
                        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5714) {
+                               if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
+                                       bmsr |= BMSR_LSTATUS;
+                               else
+                                       bmsr &= ~BMSR_LSTATUS;
+                       }
                        tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
                }
        }
@@ -2913,9 +2979,7 @@ static void tg3_tx(struct tg3 *tp)
                struct sk_buff *skb = ri->skb;
                int i;
 
-               if (unlikely(skb == NULL))
-                       BUG();
-
+               BUG_ON(skb == NULL);
                pci_unmap_single(tp->pdev,
                                 pci_unmap_addr(ri, mapping),
                                 skb_headlen(skb),
@@ -2926,12 +2990,10 @@ static void tg3_tx(struct tg3 *tp)
                sw_idx = NEXT_TX(sw_idx);
 
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       if (unlikely(sw_idx == hw_idx))
-                               BUG();
+                       BUG_ON(sw_idx == hw_idx);
 
                        ri = &tp->tx_buffers[sw_idx];
-                       if (unlikely(ri->skb != NULL))
-                               BUG();
+                       BUG_ON(ri->skb != NULL);
 
                        pci_unmap_page(tp->pdev,
                                       pci_unmap_addr(ri, mapping),
@@ -3338,6 +3400,23 @@ static inline void tg3_full_unlock(struct tg3 *tp)
        spin_unlock_bh(&tp->lock);
 }
 
+/* One-shot MSI handler - Chip automatically disables interrupt
+ * after sending MSI so driver doesn't have to do it.
+ */
+static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       struct tg3 *tp = netdev_priv(dev);
+
+       prefetch(tp->hw_status);
+       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+
+       if (likely(!tg3_irq_sync(tp)))
+               netif_rx_schedule(dev);         /* schedule NAPI poll */
+
+       return IRQ_HANDLED;
+}
+
 /* MSI ISR - No need to check for interrupt sharing and no need to
  * flush status block and interrupt mailbox. PCI ordering rules
  * guarantee that MSI will arrive after the status block.
@@ -3465,7 +3544,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
        return IRQ_RETVAL(0);
 }
 
-static int tg3_init_hw(struct tg3 *);
+static int tg3_init_hw(struct tg3 *, int);
 static int tg3_halt(struct tg3 *, int, int);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3501,7 +3580,7 @@ static void tg3_reset_task(void *_data)
        tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
-       tg3_init_hw(tp);
+       tg3_init_hw(tp, 1);
 
        tg3_netif_start(tp);
 
@@ -3537,7 +3616,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
                                          int len)
 {
 #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
-       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+       if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
                return (((u64) mapping + len) > DMA_40BIT_MASK);
        return 0;
 #else
@@ -3628,7 +3707,135 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
        txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
 }
 
+/* hard_start_xmit for devices that don't have any bugs and
+ * support TG3_FLG2_HW_TSO_2 only.
+ */
 static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       dma_addr_t mapping;
+       u32 len, entry, base_flags, mss;
+
+       len = skb_headlen(skb);
+
+       /* No BH disabling for tx_lock here.  We are running in BH disabled
+        * context and TX reclaim runs via tp->poll inside of a software
+        * interrupt.  Furthermore, IRQ processing runs lockless so we have
+        * no IRQ context deadlocks to worry about either.  Rejoice!
+        */
+       if (!spin_trylock(&tp->tx_lock))
+               return NETDEV_TX_LOCKED;
+
+       if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+               if (!netif_queue_stopped(dev)) {
+                       netif_stop_queue(dev);
+
+                       /* This is a hard error, log it. */
+                       printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+                              "queue awake!\n", dev->name);
+               }
+               spin_unlock(&tp->tx_lock);
+               return NETDEV_TX_BUSY;
+       }
+
+       entry = tp->tx_prod;
+       base_flags = 0;
+#if TG3_TSO_SUPPORT != 0
+       mss = 0;
+       if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
+           (mss = skb_shinfo(skb)->tso_size) != 0) {
+               int tcp_opt_len, ip_tcp_len;
+
+               if (skb_header_cloned(skb) &&
+                   pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                       goto out_unlock;
+               }
+
+               tcp_opt_len = ((skb->h.th->doff - 5) * 4);
+               ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
+
+               base_flags |= (TXD_FLAG_CPU_PRE_DMA |
+                              TXD_FLAG_CPU_POST_DMA);
+
+               skb->nh.iph->check = 0;
+               skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
+
+               skb->h.th->check = 0;
+
+               mss |= (ip_tcp_len + tcp_opt_len) << 9;
+       }
+       else if (skb->ip_summed == CHECKSUM_HW)
+               base_flags |= TXD_FLAG_TCPUDP_CSUM;
+#else
+       mss = 0;
+       if (skb->ip_summed == CHECKSUM_HW)
+               base_flags |= TXD_FLAG_TCPUDP_CSUM;
+#endif
+#if TG3_VLAN_TAG_USED
+       if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+               base_flags |= (TXD_FLAG_VLAN |
+                              (vlan_tx_tag_get(skb) << 16));
+#endif
+
+       /* Queue skb data, a.k.a. the main skb fragment. */
+       mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+
+       tp->tx_buffers[entry].skb = skb;
+       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
+
+       tg3_set_txd(tp, entry, mapping, len, base_flags,
+                   (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
+
+       entry = NEXT_TX(entry);
+
+       /* Now loop through additional data fragments, and queue them. */
+       if (skb_shinfo(skb)->nr_frags > 0) {
+               unsigned int i, last;
+
+               last = skb_shinfo(skb)->nr_frags - 1;
+               for (i = 0; i <= last; i++) {
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+                       len = frag->size;
+                       mapping = pci_map_page(tp->pdev,
+                                              frag->page,
+                                              frag->page_offset,
+                                              len, PCI_DMA_TODEVICE);
+
+                       tp->tx_buffers[entry].skb = NULL;
+                       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
+
+                       tg3_set_txd(tp, entry, mapping, len,
+                                   base_flags, (i == last) | (mss << 1));
+
+                       entry = NEXT_TX(entry);
+               }
+       }
+
+       /* Packets are ready, update Tx producer idx local and on card. */
+       tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
+
+       tp->tx_prod = entry;
+       if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
+               netif_stop_queue(dev);
+               if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+                       netif_wake_queue(tp->dev);
+       }
+
+out_unlock:
+       mmiowb();
+       spin_unlock(&tp->tx_lock);
+
+       dev->trans_start = jiffies;
+
+       return NETDEV_TX_OK;
+}
+
+/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
+ * support TG3_FLG2_HW_TSO_1 or firmware TSO only.
+ */
+static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
        dma_addr_t mapping;
@@ -3848,7 +4055,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 
        tg3_set_mtu(dev, tp, new_mtu);
 
-       tg3_init_hw(tp);
+       tg3_init_hw(tp, 0);
 
        tg3_netif_start(tp);
 
@@ -4278,9 +4485,8 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
 /* tp->lock is held. */
 static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
 {
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
-               tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
-                             NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+       tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+                     NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 
        if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
                switch (kind) {
@@ -4361,13 +4567,17 @@ static int tg3_chip_reset(struct tg3 *tp)
        void (*write_op)(struct tg3 *, u32, u32);
        int i;
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
-               tg3_nvram_lock(tp);
-               /* No matching tg3_nvram_unlock() after this because
-                * chip reset below will undo the nvram lock.
-                */
-               tp->nvram_lock_cnt = 0;
-       }
+       tg3_nvram_lock(tp);
+
+       /* No matching tg3_nvram_unlock() after this because
+        * chip reset below will undo the nvram lock.
+        */
+       tp->nvram_lock_cnt = 0;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+               tw32(GRC_FASTBOOT_PC, 0);
 
        /*
         * We must avoid the readl() that normally takes place.
@@ -4515,20 +4725,25 @@ static int tg3_chip_reset(struct tg3 *tp)
                tw32_f(MAC_MODE, 0);
        udelay(40);
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
-               /* Wait for firmware initialization to complete. */
-               for (i = 0; i < 100000; i++) {
-                       tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
-                       if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-                               break;
-                       udelay(10);
-               }
-               if (i >= 100000) {
-                       printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
-                              "firmware will not restart magic=%08x\n",
-                              tp->dev->name, val);
-                       return -ENODEV;
-               }
+       /* Wait for firmware initialization to complete. */
+       for (i = 0; i < 100000; i++) {
+               tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+               if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+                       break;
+               udelay(10);
+       }
+
+       /* Chip might not be fitted with firmare.  Some Sun onboard
+        * parts are configured like that.  So don't signal the timeout
+        * of the above loop as an error, but do report the lack of
+        * running firmware once.
+        */
+       if (i >= 100000 &&
+           !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
+               tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
+
+               printk(KERN_INFO PFX "%s: No firmware running.\n",
+                      tp->dev->name);
        }
 
        if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
@@ -4732,9 +4947,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 {
        int i;
 
-       if (offset == TX_CPU_BASE &&
-           (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
-               BUG();
+       BUG_ON(offset == TX_CPU_BASE &&
+           (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
 
        if (offset == RX_CPU_BASE) {
                for (i = 0; i < 10000; i++) {
@@ -5518,9 +5732,26 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
 
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
-       spin_lock_bh(&tp->lock);
-       __tg3_set_mac_addr(tp);
-       spin_unlock_bh(&tp->lock);
+       if (!netif_running(dev))
+               return 0;
+
+       if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+               /* Reset chip so that ASF can re-init any MAC addresses it
+                * needs.
+                */
+               tg3_netif_stop(tp);
+               tg3_full_lock(tp, 1);
+
+               tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+               tg3_init_hw(tp, 0);
+
+               tg3_netif_start(tp);
+               tg3_full_unlock(tp);
+       } else {
+               spin_lock_bh(&tp->lock);
+               __tg3_set_mac_addr(tp);
+               spin_unlock_bh(&tp->lock);
+       }
 
        return 0;
 }
@@ -5570,7 +5801,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 }
 
 /* tp->lock is held. */
-static int tg3_reset_hw(struct tg3 *tp)
+static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 {
        u32 val, rdmac_mode;
        int i, err, limit;
@@ -5585,6 +5816,9 @@ static int tg3_reset_hw(struct tg3 *tp)
                tg3_abort_hw(tp, 1);
        }
 
+       if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy)
+               tg3_phy_reset(tp);
+
        err = tg3_chip_reset(tp);
        if (err)
                return err;
@@ -5631,10 +5865,14 @@ static int tg3_reset_hw(struct tg3 *tp)
                          GRC_MODE_NO_TX_PHDR_CSUM |
                          GRC_MODE_NO_RX_PHDR_CSUM);
        tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-       if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
-               tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
-       if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
-               tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+       /* Pseudo-header checksum is done by hardware logic and not
+        * the offload processers, so make the chip do the pseudo-
+        * header checksums on receive.  For transmit it is more
+        * convenient to do the pseudo-header checksum in software
+        * as Linux does that on transmit for us in all cases.
+        */
+       tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 
        tw32(GRC_MODE,
             tp->grc_mode |
@@ -5955,6 +6193,9 @@ static int tg3_reset_hw(struct tg3 *tp)
                        gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
                                     GRC_LCLCTRL_GPIO_OUTPUT3;
 
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+                       gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
+
                tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
 
                /* GPIO1 must be driven high for eeprom write protect */
@@ -5993,6 +6234,11 @@ static int tg3_reset_hw(struct tg3 *tp)
                }
        }
 
+       /* Enable host coalescing bug fix */
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787))
+               val |= (1 << 29);
+
        tw32_f(WDMAC_MODE, val);
        udelay(40);
 
@@ -6048,6 +6294,9 @@ static int tg3_reset_hw(struct tg3 *tp)
        udelay(100);
 
        tp->rx_mode = RX_MODE_ENABLE;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+               tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
+
        tw32_f(MAC_RX_MODE, tp->rx_mode);
        udelay(10);
 
@@ -6097,7 +6346,18 @@ static int tg3_reset_hw(struct tg3 *tp)
                tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
        }
 
-       err = tg3_setup_phy(tp, 1);
+       if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) &&
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) {
+               u32 tmp;
+
+               tmp = tr32(SERDES_RX_CTRL);
+               tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT);
+               tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT;
+               tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT;
+               tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+       }
+
+       err = tg3_setup_phy(tp, reset_phy);
        if (err)
                return err;
 
@@ -6170,12 +6430,12 @@ static int tg3_reset_hw(struct tg3 *tp)
 /* Called at device open time to get the chip ready for
  * packet processing.  Invoked with tp->lock held.
  */
-static int tg3_init_hw(struct tg3 *tp)
+static int tg3_init_hw(struct tg3 *tp, int reset_phy)
 {
        int err;
 
        /* Force the chip into D0. */
-       err = tg3_set_power_state(tp, 0);
+       err = tg3_set_power_state(tp, PCI_D0);
        if (err)
                goto out;
 
@@ -6183,7 +6443,7 @@ static int tg3_init_hw(struct tg3 *tp)
 
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 
-       err = tg3_reset_hw(tp);
+       err = tg3_reset_hw(tp, reset_phy);
 
 out:
        return err;
@@ -6231,12 +6491,19 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
        TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG);
        TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS);
        TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE);
+
+       TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT);
+       TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT);
+       TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
 }
 
 static void tg3_timer(unsigned long __opaque)
 {
        struct tg3 *tp = (struct tg3 *) __opaque;
 
+       if (tp->irq_sync)
+               goto restart_timer;
+
        spin_lock(&tp->lock);
 
        if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
@@ -6313,11 +6580,11 @@ static void tg3_timer(unsigned long __opaque)
                if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
                        u32 val;
 
-                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
-                                          FWCMD_NICDRV_ALIVE2);
-                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
+                                     FWCMD_NICDRV_ALIVE2);
+                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
                        /* 5 seconds timeout */
-                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
+                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
                        val = tr32(GRC_RX_CPU_EVENT);
                        val |= (1 << 14);
                        tw32(GRC_RX_CPU_EVENT, val);
@@ -6327,10 +6594,31 @@ static void tg3_timer(unsigned long __opaque)
 
        spin_unlock(&tp->lock);
 
+restart_timer:
        tp->timer.expires = jiffies + tp->timer_offset;
        add_timer(&tp->timer);
 }
 
+static int tg3_request_irq(struct tg3 *tp)
+{
+       irqreturn_t (*fn)(int, void *, struct pt_regs *);
+       unsigned long flags;
+       struct net_device *dev = tp->dev;
+
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+               fn = tg3_msi;
+               if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
+                       fn = tg3_msi_1shot;
+               flags = SA_SAMPLE_RANDOM;
+       } else {
+               fn = tg3_interrupt;
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+                       fn = tg3_interrupt_tagged;
+               flags = SA_SHIRQ | SA_SAMPLE_RANDOM;
+       }
+       return (request_irq(tp->pdev->irq, fn, flags, dev->name, dev));
+}
+
 static int tg3_test_interrupt(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
@@ -6367,16 +6655,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
 
        free_irq(tp->pdev->irq, dev);
        
-       if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
-               err = request_irq(tp->pdev->irq, tg3_msi,
-                                 SA_SAMPLE_RANDOM, dev->name, dev);
-       else {
-               irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
-               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
-                       fn = tg3_interrupt_tagged;
-               err = request_irq(tp->pdev->irq, fn,
-                                 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-       }
+       err = tg3_request_irq(tp);
 
        if (err)
                return err;
@@ -6428,14 +6707,7 @@ static int tg3_test_msi(struct tg3 *tp)
 
        tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
 
-       {
-               irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
-               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
-                       fn = tg3_interrupt_tagged;
-
-               err = request_irq(tp->pdev->irq, fn,
-                                 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-       }
+       err = tg3_request_irq(tp);
        if (err)
                return err;
 
@@ -6445,7 +6717,7 @@ static int tg3_test_msi(struct tg3 *tp)
        tg3_full_lock(tp, 1);
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-       err = tg3_init_hw(tp);
+       err = tg3_init_hw(tp, 1);
 
        tg3_full_unlock(tp);
 
@@ -6462,6 +6734,10 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_lock(tp, 0);
 
+       err = tg3_set_power_state(tp, PCI_D0);
+       if (err)
+               return err;
+
        tg3_disable_ints(tp);
        tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 
@@ -6476,7 +6752,9 @@ static int tg3_open(struct net_device *dev)
 
        if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
            (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
-           (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) {
+           (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) &&
+           !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
+             (tp->pdev_peer == tp->pdev))) {
                /* All MSI supporting chips should support tagged
                 * status.  Assert that this is the case.
                 */
@@ -6491,17 +6769,7 @@ static int tg3_open(struct net_device *dev)
                        tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
                }
        }
-       if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
-               err = request_irq(tp->pdev->irq, tg3_msi,
-                                 SA_SAMPLE_RANDOM, dev->name, dev);
-       else {
-               irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
-               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
-                       fn = tg3_interrupt_tagged;
-
-               err = request_irq(tp->pdev->irq, fn,
-                                 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-       }
+       err = tg3_request_irq(tp);
 
        if (err) {
                if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -6514,7 +6782,7 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_lock(tp, 0);
 
-       err = tg3_init_hw(tp);
+       err = tg3_init_hw(tp, 1);
        if (err) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
                tg3_free_rings(tp);
@@ -6566,6 +6834,14 @@ static int tg3_open(struct net_device *dev)
 
                        return err;
                }
+
+               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+                       if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
+                               u32 val = tr32(0x7c04);
+
+                               tw32(0x7c04, val | (1 << 29));
+                       }
+               }
        }
 
        tg3_full_lock(tp, 0);
@@ -6839,7 +7115,6 @@ static int tg3_close(struct net_device *dev)
        tp->tg3_flags &=
                ~(TG3_FLAG_INIT_COMPLETE |
                  TG3_FLAG_GOT_SERDES_FLOWCTL);
-       netif_carrier_off(tp->dev);
 
        tg3_full_unlock(tp);
 
@@ -6856,6 +7131,10 @@ static int tg3_close(struct net_device *dev)
 
        tg3_free_consistent(tp);
 
+       tg3_set_power_state(tp, PCI_D3hot);
+
+       netif_carrier_off(tp->dev);
+
        return 0;
 }
 
@@ -7150,6 +7429,9 @@ static void tg3_set_rx_mode(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
+       if (!netif_running(dev))
+               return;
+
        tg3_full_lock(tp, 0);
        __tg3_set_rx_mode(dev);
        tg3_full_unlock(tp);
@@ -7174,6 +7456,9 @@ static void tg3_get_regs(struct net_device *dev,
 
        memset(p, 0, TG3_REGDUMP_LEN);
 
+       if (tp->link_config.phy_is_low_power)
+               return;
+
        tg3_full_lock(tp, 0);
 
 #define __GET_REG32(reg)       (*(p)++ = tr32(reg))
@@ -7240,6 +7525,7 @@ static int tg3_get_eeprom_len(struct net_device *dev)
 }
 
 static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val);
+static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val);
 
 static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
 {
@@ -7248,6 +7534,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        u8  *pd;
        u32 i, offset, len, val, b_offset, b_count;
 
+       if (tp->link_config.phy_is_low_power)
+               return -EAGAIN;
+
        offset = eeprom->offset;
        len = eeprom->len;
        eeprom->len = 0;
@@ -7309,6 +7598,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        u32 offset, len, b_offset, odd_len, start, end;
        u8 *buf;
 
+       if (tp->link_config.phy_is_low_power)
+               return -EAGAIN;
+
        if (eeprom->magic != TG3_EEPROM_MAGIC)
                return -EINVAL;
 
@@ -7444,6 +7736,7 @@ static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
   
        strcpy(info->driver, DRV_MODULE_NAME);
        strcpy(info->version, DRV_MODULE_VERSION);
+       strcpy(info->fw_version, tp->fw_ver);
        strcpy(info->bus_info, pci_name(tp->pdev));
 }
   
@@ -7538,11 +7831,20 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
   
        ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
        ering->rx_mini_max_pending = 0;
-       ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
+       if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
+               ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
+       else
+               ering->rx_jumbo_max_pending = 0;
+
+       ering->tx_max_pending = TG3_TX_RING_SIZE - 1;
 
        ering->rx_pending = tp->rx_pending;
        ering->rx_mini_pending = 0;
-       ering->rx_jumbo_pending = tp->rx_jumbo_pending;
+       if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
+               ering->rx_jumbo_pending = tp->rx_jumbo_pending;
+       else
+               ering->rx_jumbo_pending = 0;
+
        ering->tx_pending = tp->tx_pending;
 }
   
@@ -7573,7 +7875,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 
        if (netif_running(dev)) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               tg3_init_hw(tp);
+               tg3_init_hw(tp, 1);
                tg3_netif_start(tp);
        }
 
@@ -7618,7 +7920,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 
        if (netif_running(dev)) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               tg3_init_hw(tp);
+               tg3_init_hw(tp, 1);
                tg3_netif_start(tp);
        }
 
@@ -7663,10 +7965,11 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
                return 0;
        }
   
-       if (data)
-               dev->features |= NETIF_F_IP_CSUM;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+               ethtool_op_set_tx_hw_csum(dev, data);
        else
-               dev->features &= ~NETIF_F_IP_CSUM;
+               ethtool_op_set_tx_csum(dev, data);
 
        return 0;
 }
@@ -7736,29 +8039,56 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
 }
 
 #define NVRAM_TEST_SIZE 0x100
+#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
-       u32 *buf, csum;
-       int i, j, err = 0;
+       u32 *buf, csum, magic;
+       int i, j, err = 0, size;
+
+       if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
+               return -EIO;
 
-       buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL);
+       if (magic == TG3_EEPROM_MAGIC)
+               size = NVRAM_TEST_SIZE;
+       else if ((magic & 0xff000000) == 0xa5000000) {
+               if ((magic & 0xe00000) == 0x200000)
+                       size = NVRAM_SELFBOOT_FORMAT1_SIZE;
+               else
+                       return 0;
+       } else
+               return -EIO;
+
+       buf = kmalloc(size, GFP_KERNEL);
        if (buf == NULL)
                return -ENOMEM;
 
-       for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) {
+       err = -EIO;
+       for (i = 0, j = 0; i < size; i += 4, j++) {
                u32 val;
 
                if ((err = tg3_nvram_read(tp, i, &val)) != 0)
                        break;
                buf[j] = cpu_to_le32(val);
        }
-       if (i < NVRAM_TEST_SIZE)
+       if (i < size)
                goto out;
 
-       err = -EIO;
-       if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC)
+       /* Selfboot format */
+       if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) {
+               u8 *buf8 = (u8 *) buf, csum8 = 0;
+
+               for (i = 0; i < size; i++)
+                       csum8 += buf8[i];
+
+               if (csum8 == 0) {
+                       err = 0;
+                       goto out;
+               }
+
+               err = -EIO;
                goto out;
+       }
 
        /* Bootstrap checksum at offset 0x10 */
        csum = calc_crc((unsigned char *) buf, 0x10);
@@ -8018,7 +8348,7 @@ out:
 
 static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
 {
-       static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a };
+       static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a };
        int i;
        u32 j;
 
@@ -8052,14 +8382,25 @@ static int tg3_test_memory(struct tg3 *tp)
                { 0x00008000, 0x02000},
                { 0x00010000, 0x0e000},
                { 0xffffffff, 0x00000}
+       }, mem_tbl_5755[] = {
+               { 0x00000200, 0x00008},
+               { 0x00004000, 0x00800},
+               { 0x00006000, 0x00800},
+               { 0x00008000, 0x02000},
+               { 0x00010000, 0x0c000},
+               { 0xffffffff, 0x00000}
        };
        struct mem_entry *mem_tbl;
        int err = 0;
        int i;
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
-               mem_tbl = mem_tbl_5705;
-       else
+       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+                       mem_tbl = mem_tbl_5755;
+               else
+                       mem_tbl = mem_tbl_5705;
+       } else
                mem_tbl = mem_tbl_570x;
 
        for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
@@ -8108,8 +8449,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                }
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
                           MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
-               if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+               if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
                        mac_mode &= ~MAC_MODE_LINK_POLARITY;
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                                    MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+               }
                tw32(MAC_MODE, mac_mode);
        }
        else
@@ -8119,6 +8463,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
        tx_len = 1514;
        skb = dev_alloc_skb(tx_len);
+       if (!skb)
+               return -ENOMEM;
+
        tx_data = skb_put(skb, tx_len);
        memcpy(tx_data, tp->dev->dev_addr, 6);
        memset(tx_data + 6, 0x0, 8);
@@ -8214,7 +8561,7 @@ static int tg3_test_loopback(struct tg3 *tp)
        if (!netif_running(tp->dev))
                return TG3_LOOPBACK_FAILED;
 
-       tg3_reset_hw(tp);
+       tg3_reset_hw(tp, 1);
 
        if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
                err |= TG3_MAC_LOOPBACK_FAILED;
@@ -8231,6 +8578,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 {
        struct tg3 *tp = netdev_priv(dev);
 
+       if (tp->link_config.phy_is_low_power)
+               tg3_set_power_state(tp, PCI_D0);
+
        memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
 
        if (tg3_test_nvram(tp) != 0) {
@@ -8259,6 +8609,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                if (!err)
                        tg3_nvram_unlock(tp);
 
+               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+                       tg3_phy_reset(tp);
+
                if (tg3_test_registers(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
                        data[2] = 1;
@@ -8282,12 +8635,15 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
                if (netif_running(dev)) {
                        tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-                       tg3_init_hw(tp);
+                       tg3_init_hw(tp, 1);
                        tg3_netif_start(tp);
                }
 
                tg3_full_unlock(tp);
        }
+       if (tp->link_config.phy_is_low_power)
+               tg3_set_power_state(tp, PCI_D3hot);
+
 }
 
 static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -8307,6 +8663,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
                        break;                  /* We have no PHY */
 
+               if (tp->link_config.phy_is_low_power)
+                       return -EAGAIN;
+
                spin_lock_bh(&tp->lock);
                err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
                spin_unlock_bh(&tp->lock);
@@ -8323,6 +8682,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
+               if (tp->link_config.phy_is_low_power)
+                       return -EAGAIN;
+
                spin_lock_bh(&tp->lock);
                err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
                spin_unlock_bh(&tp->lock);
@@ -8466,14 +8828,14 @@ static struct ethtool_ops tg3_ethtool_ops = {
 
 static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
 {
-       u32 cursize, val;
+       u32 cursize, val, magic;
 
        tp->nvram_size = EEPROM_CHIP_SIZE;
 
-       if (tg3_nvram_read(tp, 0, &val) != 0)
+       if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
                return;
 
-       if (swab32(val) != TG3_EEPROM_MAGIC)
+       if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000))
                return;
 
        /*
@@ -8481,13 +8843,13 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
         * When we encounter our validation signature, we know the addressing
         * has wrapped around, and thus have our chip size.
         */
-       cursize = 0x800;
+       cursize = 0x10;
 
        while (cursize < tp->nvram_size) {
-               if (tg3_nvram_read(tp, cursize, &val) != 0)
+               if (tg3_nvram_read_swab(tp, cursize, &val) != 0)
                        return;
 
-               if (swab32(val) == TG3_EEPROM_MAGIC)
+               if (val == magic)
                        break;
 
                cursize <<= 1;
@@ -8500,6 +8862,15 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
 {
        u32 val;
 
+       if (tg3_nvram_read_swab(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) {
                        tp->nvram_size = (val >> 16) * 1024;
@@ -8623,14 +8994,90 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
        }
 }
 
+static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1;
+
+       nvcfg1 = tr32(NVRAM_CFG1);
+
+       /* NVRAM protection for TPM */
+       if (nvcfg1 & (1 << 27))
+               tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ:
+               case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ:
+                       tp->nvram_jedecnum = JEDEC_ATMEL;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+                       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:
+               case FLASH_5755VENDOR_ATMEL_FLASH_4:
+                       tp->nvram_jedecnum = JEDEC_ATMEL;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->tg3_flags2 |= TG3_FLG2_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;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->tg3_flags2 |= TG3_FLG2_FLASH;
+                       tp->nvram_pagesize = 256;
+                       break;
+       }
+}
+
+static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1;
+
+       nvcfg1 = tr32(NVRAM_CFG1);
+
+       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;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+                       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;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->tg3_flags2 |= TG3_FLG2_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;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->tg3_flags2 |= TG3_FLG2_FLASH;
+                       tp->nvram_pagesize = 256;
+                       break;
+       }
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
        int j;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
-               return;
-
        tw32_f(GRC_EEPROM_ADDR,
             (EEPROM_ADDR_FSM_RESET |
              (EEPROM_DEFAULT_CLOCK_PERIOD <<
@@ -8658,6 +9105,10 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
 
                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)
+                       tg3_get_5787_nvram_info(tp);
                else
                        tg3_get_nvram_info(tp);
 
@@ -8727,26 +9178,42 @@ static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
        return 0;
 }
 
+static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
+{
+       if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
+           (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
+           (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+           (tp->nvram_jedecnum == JEDEC_ATMEL))
+
+               addr = ((addr / tp->nvram_pagesize) <<
+                       ATMEL_AT45DB0X1B_PAGE_POS) +
+                      (addr % tp->nvram_pagesize);
+
+       return addr;
+}
+
+static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr)
+{
+       if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
+           (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
+           (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+           (tp->nvram_jedecnum == JEDEC_ATMEL))
+
+               addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) *
+                       tp->nvram_pagesize) +
+                      (addr & ((1 << ATMEL_AT45DB0X1B_PAGE_POS) - 1));
+
+       return addr;
+}
+
 static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
 {
        int ret;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
-               return -EINVAL;
-       }
-
        if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
                return tg3_nvram_read_using_eeprom(tp, offset, val);
 
-       if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
-               (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
-               (tp->nvram_jedecnum == JEDEC_ATMEL)) {
-
-               offset = ((offset / tp->nvram_pagesize) <<
-                         ATMEL_AT45DB0X1B_PAGE_POS) +
-                       (offset % tp->nvram_pagesize);
-       }
+       offset = tg3_nvram_phys_addr(tp, offset);
 
        if (offset > NVRAM_ADDR_MSK)
                return -EINVAL;
@@ -8771,6 +9238,16 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
        return ret;
 }
 
+static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val)
+{
+       int err;
+       u32 tmp;
+
+       err = tg3_nvram_read(tp, offset, &tmp);
+       *val = swab32(tmp);
+       return err;
+}
+
 static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
                                    u32 offset, u32 len, u8 *buf)
 {
@@ -8923,15 +9400,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
 
                page_off = offset % tp->nvram_pagesize;
 
-               if ((tp->tg3_flags2 & TG3_FLG2_FLASH) &&
-                       (tp->nvram_jedecnum == JEDEC_ATMEL)) {
-
-                       phy_addr = ((offset / tp->nvram_pagesize) <<
-                                   ATMEL_AT45DB0X1B_PAGE_POS) + page_off;
-               }
-               else {
-                       phy_addr = offset;
-               }
+               phy_addr = tg3_nvram_phys_addr(tp, offset);
 
                tw32(NVRAM_ADDR, phy_addr);
 
@@ -8939,13 +9408,15 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
 
                if ((page_off == 0) || (i == 0))
                        nvram_cmd |= NVRAM_CMD_FIRST;
-               else if (page_off == (tp->nvram_pagesize - 4))
+               if (page_off == (tp->nvram_pagesize - 4))
                        nvram_cmd |= NVRAM_CMD_LAST;
 
                if (i == (len - 4))
                        nvram_cmd |= NVRAM_CMD_LAST;
 
                if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
+                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
+                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) &&
                    (tp->nvram_jedecnum == JEDEC_ST) &&
                    (nvram_cmd & NVRAM_CMD_FIRST)) {
 
@@ -8971,11 +9442,6 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
 {
        int ret;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n");
-               return -EINVAL;
-       }
-
        if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
                tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
                       ~GRC_LCLCTRL_GPIO_OUTPUT1);
@@ -9083,12 +9549,18 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
        return NULL;
 }
 
-/* Since this function may be called in D3-hot power state during
- * tg3_init_one(), only config cycles are allowed.
- */
 static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 {
        u32 val;
+       u16 pmcsr;
+
+       /* On some early chips the SRAM cannot be accessed in D3hot state,
+        * so need make sure we're in D0.
+        */
+       pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
+       pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+       pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
+       msleep(1);
 
        /* Make sure register accesses (indirect or otherwise)
         * will function correctly.
@@ -9096,9 +9568,20 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
                               tp->misc_host_ctrl);
 
+       /* The memory arbiter has to be enabled in order for SRAM accesses
+        * to succeed.  Normally on powerup the tg3 chip firmware will make
+        * sure it is enabled, but other entities such as system netboot
+        * code might disable it.
+        */
+       val = tr32(MEMARB_MODE);
+       tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
        tp->phy_id = PHY_ID_INVALID;
        tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
+       /* Assume an onboard device by default.  */
+       tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
                u32 nic_cfg, led_cfg;
@@ -9195,10 +9678,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
                        tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-               if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
-                   (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
+               if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
                        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+               else
+                       tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
 
                if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
                        tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
@@ -9344,32 +9827,55 @@ skip_phy_reset:
 static void __devinit tg3_read_partno(struct tg3 *tp)
 {
        unsigned char vpd_data[256];
-       unsigned int i;
+       int i;
+       u32 magic;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               /* Sun decided not to put the necessary bits in the
-                * NVRAM of their onboard tg3 parts :(
-                */
-               strcpy(tp->board_part_number, "Sun 570X");
-               return;
-       }
+       if (tg3_nvram_read_swab(tp, 0x0, &magic))
+               goto out_not_found;
 
-       for (i = 0; i < 256; i += 4) {
-               u32 tmp;
+       if (magic == TG3_EEPROM_MAGIC) {
+               for (i = 0; i < 256; i += 4) {
+                       u32 tmp;
 
-               if (tg3_nvram_read(tp, 0x100 + i, &tmp))
-                       goto out_not_found;
+                       if (tg3_nvram_read(tp, 0x100 + i, &tmp))
+                               goto out_not_found;
 
-               vpd_data[i + 0] = ((tmp >>  0) & 0xff);
-               vpd_data[i + 1] = ((tmp >>  8) & 0xff);
-               vpd_data[i + 2] = ((tmp >> 16) & 0xff);
-               vpd_data[i + 3] = ((tmp >> 24) & 0xff);
+                       vpd_data[i + 0] = ((tmp >>  0) & 0xff);
+                       vpd_data[i + 1] = ((tmp >>  8) & 0xff);
+                       vpd_data[i + 2] = ((tmp >> 16) & 0xff);
+                       vpd_data[i + 3] = ((tmp >> 24) & 0xff);
+               }
+       } else {
+               int vpd_cap;
+
+               vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD);
+               for (i = 0; i < 256; i += 4) {
+                       u32 tmp, j = 0;
+                       u16 tmp16;
+
+                       pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR,
+                                             i);
+                       while (j++ < 100) {
+                               pci_read_config_word(tp->pdev, vpd_cap +
+                                                    PCI_VPD_ADDR, &tmp16);
+                               if (tmp16 & 0x8000)
+                                       break;
+                               msleep(1);
+                       }
+                       if (!(tmp16 & 0x8000))
+                               goto out_not_found;
+
+                       pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
+                                             &tmp);
+                       tmp = cpu_to_le32(tmp);
+                       memcpy(&vpd_data[i], &tmp, 4);
+               }
        }
 
        /* Now parse and find the part number. */
-       for (i = 0; i < 254; ) {
+       for (i = 0; i < 256; ) {
                unsigned char val = vpd_data[i];
-               unsigned int block_end;
+               int block_end;
 
                if (val == 0x82 || val == 0x91) {
                        i = (i + 3 +
@@ -9385,26 +9891,21 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
                             (vpd_data[i + 1] +
                              (vpd_data[i + 2] << 8)));
                i += 3;
-
-               if (block_end > 256)
-                       goto out_not_found;
-
-               while (i < (block_end - 2)) {
+               while (i < block_end) {
                        if (vpd_data[i + 0] == 'P' &&
                            vpd_data[i + 1] == 'N') {
                                int partno_len = vpd_data[i + 2];
 
-                               i += 3;
-                               if (partno_len > 24 || (partno_len + i) > 256)
+                               if (partno_len > 24)
                                        goto out_not_found;
 
                                memcpy(tp->board_part_number,
-                                      &vpd_data[i], partno_len);
+                                      &vpd_data[i + 3],
+                                      partno_len);
 
                                /* Success. */
                                return;
                        }
-                       i += 3 + vpd_data[i + 2];
                }
 
                /* Part number not found. */
@@ -9415,36 +9916,45 @@ out_not_found:
        strcpy(tp->board_part_number, "none");
 }
 
-#ifdef CONFIG_SPARC64
-static int __devinit tg3_is_sun_570X(struct tg3 *tp)
+static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
-       struct pci_dev *pdev = tp->pdev;
-       struct pcidev_cookie *pcp = pdev->sysdata;
+       u32 val, offset, start;
 
-       if (pcp != NULL) {
-               int node = pcp->prom_node;
-               u32 venid;
-               int err;
+       if (tg3_nvram_read_swab(tp, 0, &val))
+               return;
 
-               err = prom_getproperty(node, "subsystem-vendor-id",
-                                      (char *) &venid, sizeof(venid));
-               if (err == 0 || err == -1)
-                       return 0;
-               if (venid == PCI_VENDOR_ID_SUN)
-                       return 1;
-
-               /* TG3 chips onboard the SunBlade-2500 don't have the
-                * subsystem-vendor-id set to PCI_VENDOR_ID_SUN but they
-                * are distinguishable from non-Sun variants by being
-                * named "network" by the firmware.  Non-Sun cards will
-                * show up as being named "ethernet".
-                */
-               if (!strcmp(pcp->prom_name, "network"))
-                       return 1;
+       if (val != TG3_EEPROM_MAGIC)
+               return;
+
+       if (tg3_nvram_read_swab(tp, 0xc, &offset) ||
+           tg3_nvram_read_swab(tp, 0x4, &start))
+               return;
+
+       offset = tg3_nvram_logical_addr(tp, offset);
+       if (tg3_nvram_read_swab(tp, offset, &val))
+               return;
+
+       if ((val & 0xfc000000) == 0x0c000000) {
+               u32 ver_offset, addr;
+               int i;
+
+               if (tg3_nvram_read_swab(tp, offset + 4, &val) ||
+                   tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
+                       return;
+
+               if (val != 0)
+                       return;
+
+               addr = offset + ver_offset - start;
+               for (i = 0; i < 16; i += 4) {
+                       if (tg3_nvram_read(tp, addr + i, &val))
+                               return;
+
+                       val = cpu_to_le32(val);
+                       memcpy(tp->fw_ver + i, &val, 4);
+               }
        }
-       return 0;
 }
-#endif
 
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
@@ -9462,11 +9972,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        u16 pci_cmd;
        int err;
 
-#ifdef CONFIG_SPARC64
-       if (tg3_is_sun_570X(tp))
-               tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
-#endif
-
        /* 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
@@ -9606,6 +10111,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        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_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
@@ -9613,12 +10120,20 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
                tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
-       if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
-               tp->tg3_flags2 |= TG3_FLG2_HW_TSO;
+       if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
+                       tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
+                       tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
+               } else
+                       tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1;
+       }
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
            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_5752 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)
                tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
 
        if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
@@ -9749,6 +10264,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
        }
 
+       if (tp->write32 == tg3_write_indirect_reg32 ||
+           ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
+               tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
+
        /* Get eeprom hw config before calling tg3_set_power_state().
         * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
         * determined before calling tg3_set_power_state() so that
@@ -9774,8 +10295,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
                tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+               tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+
        /* Force the chip into D0. */
-       err = tg3_set_power_state(tp, 0);
+       err = tg3_set_power_state(tp, PCI_D0);
        if (err) {
                printk(KERN_ERR PFX "(%s) transition to D0 failed\n",
                       pci_name(tp->pdev));
@@ -9788,15 +10312,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
                tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
 
-       /* Pseudo-header checksum is done by hardware logic and not
-        * the offload processers, so make the chip do the pseudo-
-        * header checksums on receive.  For transmit it is more
-        * convenient to do the pseudo-header checksum in software
-        * as Linux does that on transmit for us in all cases.
-        */
-       tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
-       tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
-
        /* Derive initial jumbo mode from MTU assigned in
         * ether_setup() via the alloc_etherdev() call
         */
@@ -9828,8 +10343,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
                tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
-               tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+                       tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
+               else
+                       tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+       }
 
        tp->coalesce_mode = 0;
        if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
@@ -9928,6 +10448,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        }
 
        tg3_read_partno(tp);
+       tg3_read_fw_ver(tp);
 
        if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
                tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
@@ -9963,10 +10484,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        else
                tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
 
-       /* It seems all chips can get confused if TX buffers
+       /* All chips before 5787 can get confused if TX buffers
         * straddle the 4GB address boundary in some cases.
         */
-       tp->dev->hard_start_xmit = tg3_start_xmit;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+               tp->dev->hard_start_xmit = tg3_start_xmit;
+       else
+               tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
 
        tp->rx_offset = 2;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
@@ -10015,6 +10540,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
        u32 hi, lo, mac_offset;
+       int addr_ok = 0;
 
 #ifdef CONFIG_SPARC64
        if (!tg3_get_macaddr_sparc(tp))
@@ -10022,8 +10548,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #endif
 
        mac_offset = 0x7c;
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-            !(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
                if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
                        mac_offset = 0xcc;
@@ -10044,29 +10569,33 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
                dev->dev_addr[3] = (lo >> 16) & 0xff;
                dev->dev_addr[4] = (lo >>  8) & 0xff;
                dev->dev_addr[5] = (lo >>  0) & 0xff;
-       }
-       /* Next, try NVRAM. */
-       else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
-                !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
-                !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
-               dev->dev_addr[0] = ((hi >> 16) & 0xff);
-               dev->dev_addr[1] = ((hi >> 24) & 0xff);
-               dev->dev_addr[2] = ((lo >>  0) & 0xff);
-               dev->dev_addr[3] = ((lo >>  8) & 0xff);
-               dev->dev_addr[4] = ((lo >> 16) & 0xff);
-               dev->dev_addr[5] = ((lo >> 24) & 0xff);
-       }
-       /* Finally just fetch it out of the MAC control regs. */
-       else {
-               hi = tr32(MAC_ADDR_0_HIGH);
-               lo = tr32(MAC_ADDR_0_LOW);
 
-               dev->dev_addr[5] = lo & 0xff;
-               dev->dev_addr[4] = (lo >> 8) & 0xff;
-               dev->dev_addr[3] = (lo >> 16) & 0xff;
-               dev->dev_addr[2] = (lo >> 24) & 0xff;
-               dev->dev_addr[1] = hi & 0xff;
-               dev->dev_addr[0] = (hi >> 8) & 0xff;
+               /* Some old bootcode may report a 0 MAC address in SRAM */
+               addr_ok = is_valid_ether_addr(&dev->dev_addr[0]);
+       }
+       if (!addr_ok) {
+               /* Next, try NVRAM. */
+               if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+                   !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
+                       dev->dev_addr[0] = ((hi >> 16) & 0xff);
+                       dev->dev_addr[1] = ((hi >> 24) & 0xff);
+                       dev->dev_addr[2] = ((lo >>  0) & 0xff);
+                       dev->dev_addr[3] = ((lo >>  8) & 0xff);
+                       dev->dev_addr[4] = ((lo >> 16) & 0xff);
+                       dev->dev_addr[5] = ((lo >> 24) & 0xff);
+               }
+               /* Finally just fetch it out of the MAC control regs. */
+               else {
+                       hi = tr32(MAC_ADDR_0_HIGH);
+                       lo = tr32(MAC_ADDR_0_LOW);
+
+                       dev->dev_addr[5] = lo & 0xff;
+                       dev->dev_addr[4] = (lo >> 8) & 0xff;
+                       dev->dev_addr[3] = (lo >> 16) & 0xff;
+                       dev->dev_addr[2] = (lo >> 24) & 0xff;
+                       dev->dev_addr[1] = hi & 0xff;
+                       dev->dev_addr[0] = (hi >> 8) & 0xff;
+               }
        }
 
        if (!is_valid_ether_addr(&dev->dev_addr[0])) {
@@ -10494,7 +11023,6 @@ static void __devinit tg3_init_link_config(struct tg3 *tp)
        tp->link_config.speed = SPEED_INVALID;
        tp->link_config.duplex = DUPLEX_INVALID;
        tp->link_config.autoneg = AUTONEG_ENABLE;
-       netif_carrier_off(tp->dev);
        tp->link_config.active_speed = SPEED_INVALID;
        tp->link_config.active_duplex = DUPLEX_INVALID;
        tp->link_config.phy_is_low_power = 0;
@@ -10553,6 +11081,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case PHY_ID_BCM5752:    return "5752";
        case PHY_ID_BCM5714:    return "5714";
        case PHY_ID_BCM5780:    return "5780";
+       case PHY_ID_BCM5755:    return "5755";
+       case PHY_ID_BCM5787:    return "5787";
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
@@ -10851,11 +11381,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
        }
 
-       /* TSO is off by default, user can enable using ethtool.  */
-#if 0
-       if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)
+       /* TSO is on by default on chips that support HW_TSO_2.
+        * Some HW_TSO_1 capable chips have bugs that can lead to
+        * tx timeouts in some cases when TSO is enabled.
+        * Firmware TSO on older chips gives lower performance, so it
+        * is off by default, but can be enabled using ethtool.
+        */
+       if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 &&
+            tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2))
                dev->features |= NETIF_F_TSO;
-#endif
 
 #endif
 
@@ -10899,7 +11434,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         * checksumming.
         */
        if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
-               dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+                       dev->features |= NETIF_F_HW_CSUM;
+               else
+                       dev->features |= NETIF_F_IP_CSUM;
+               dev->features |= NETIF_F_SG;
                tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
        } else
                tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
@@ -10952,6 +11492,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
               (pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
                (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
 
+       netif_carrier_off(tp->dev);
+
        return 0;
 
 err_out_iounmap:
@@ -11022,7 +11564,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
                tg3_full_lock(tp, 0);
 
                tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-               tg3_init_hw(tp);
+               tg3_init_hw(tp, 1);
 
                tp->timer.expires = jiffies + tp->timer_offset;
                add_timer(&tp->timer);
@@ -11047,7 +11589,7 @@ static int tg3_resume(struct pci_dev *pdev)
 
        pci_restore_state(tp->pdev);
 
-       err = tg3_set_power_state(tp, 0);
+       err = tg3_set_power_state(tp, PCI_D0);
        if (err)
                return err;
 
@@ -11056,7 +11598,7 @@ static int tg3_resume(struct pci_dev *pdev)
        tg3_full_lock(tp, 0);
 
        tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-       tg3_init_hw(tp);
+       tg3_init_hw(tp, 1);
 
        tp->timer.expires = jiffies + tp->timer_offset;
        add_timer(&tp->timer);
index 7e3b613..cd68f46 100644 (file)
 #define  CHIPREV_ID_5750_A0             0x4000
 #define  CHIPREV_ID_5750_A1             0x4001
 #define  CHIPREV_ID_5750_A3             0x4003
+#define  CHIPREV_ID_5750_C2             0x4202
 #define  CHIPREV_ID_5752_A0_HW          0x5000
 #define  CHIPREV_ID_5752_A0             0x6000
 #define  CHIPREV_ID_5752_A1             0x6001
 #define   ASIC_REV_5752                         0x06
 #define   ASIC_REV_5780                         0x08
 #define   ASIC_REV_5714                         0x09
+#define   ASIC_REV_5755                         0x0a
+#define   ASIC_REV_5787                         0x0b
 #define  GET_CHIP_REV(CHIP_REV_ID)     ((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX               0x70
 #define   CHIPREV_5700_BX               0x71
 #define  RX_MODE_PROMISC                0x00000100
 #define  RX_MODE_NO_CRC_CHECK           0x00000200
 #define  RX_MODE_KEEP_VLAN_TAG          0x00000400
+#define  RX_MODE_IPV6_CSUM_ENABLE       0x01000000
 #define MAC_RX_STATUS                  0x0000046c
 #define  RX_STATUS_REMOTE_TX_XOFFED     0x00000001
 #define  RX_STATUS_XOFF_RCVD            0x00000002
 #define  GRC_LCLCTRL_CLEARINT          0x00000002
 #define  GRC_LCLCTRL_SETINT            0x00000004
 #define  GRC_LCLCTRL_INT_ON_ATTN       0x00000008
+#define  GRC_LCLCTRL_GPIO_UART_SEL     0x00000010      /* 5755 only */
 #define  GRC_LCLCTRL_USE_SIG_DETECT    0x00000010      /* 5714/5780 only */
 #define  GRC_LCLCTRL_USE_EXT_SIG_DETECT        0x00000020      /* 5714/5780 only */
 #define  GRC_LCLCTRL_GPIO_INPUT3       0x00000020
 #define GRC_MDI_CTRL                   0x00006844
 #define GRC_SEEPROM_DELAY              0x00006848
 /* 0x684c --> 0x6c00 unused */
+#define GRC_FASTBOOT_PC                        0x00006894      /* 5752, 5755, 5787 */
 
 /* 0x6c00 --> 0x7000 unused */
 
 #define  FLASH_5752VENDOR_ST_M45PE10    0x02400000
 #define  FLASH_5752VENDOR_ST_M45PE20    0x02400002
 #define  FLASH_5752VENDOR_ST_M45PE40    0x02400001
+#define  FLASH_5755VENDOR_ATMEL_FLASH_1         0x03400001
+#define  FLASH_5755VENDOR_ATMEL_FLASH_2         0x03400002
+#define  FLASH_5755VENDOR_ATMEL_FLASH_3         0x03400000
+#define  FLASH_5755VENDOR_ATMEL_FLASH_4         0x00000003
+#define  FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ    0x03c00003
+#define  FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ   0x03c00002
+#define  FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ    0x03000003
+#define  FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ   0x03000002
+#define  FLASH_5787VENDOR_MICRO_EEPROM_64KHZ    0x03000000
+#define  FLASH_5787VENDOR_MICRO_EEPROM_376KHZ   0x02000000
 #define  NVRAM_CFG1_5752PAGE_SIZE_MASK  0x70000000
 #define  FLASH_5752PAGE_SIZE_256        0x00000000
 #define  FLASH_5752PAGE_SIZE_512        0x10000000
@@ -2156,8 +2172,7 @@ struct tg3 {
 #define TG3_FLAG_PCIX_MODE             0x00020000
 #define TG3_FLAG_PCI_HIGH_SPEED                0x00040000
 #define TG3_FLAG_PCI_32BIT             0x00080000
-#define TG3_FLAG_NO_TX_PSEUDO_CSUM     0x00100000
-#define TG3_FLAG_NO_RX_PSEUDO_CSUM     0x00200000
+#define TG3_FLAG_SRAM_USE_CONFIG       0x00100000
 #define TG3_FLAG_SERDES_WOL_CAP                0x00400000
 #define TG3_FLAG_JUMBO_RING_ENABLE     0x00800000
 #define TG3_FLAG_10_100_ONLY           0x01000000
@@ -2170,7 +2185,7 @@ struct tg3 {
 #define TG3_FLAG_INIT_COMPLETE         0x80000000
        u32                             tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER         0x00000001
-#define TG3_FLG2_SUN_570X              0x00000002
+/*                                     0x00000002 available */
 #define TG3_FLG2_NO_ETH_WIRE_SPEED     0x00000004
 #define TG3_FLG2_IS_5788               0x00000008
 #define TG3_FLG2_MAX_RXPEND_64         0x00000010
@@ -2185,7 +2200,7 @@ struct tg3 {
 #define TG3_FLG2_PHY_SERDES            0x00002000
 #define TG3_FLG2_CAPACITIVE_COUPLING   0x00004000
 #define TG3_FLG2_FLASH                 0x00008000
-#define TG3_FLG2_HW_TSO                        0x00010000
+#define TG3_FLG2_HW_TSO_1              0x00010000
 #define TG3_FLG2_SERDES_PREEMPHASIS    0x00020000
 #define TG3_FLG2_5705_PLUS             0x00040000
 #define TG3_FLG2_5750_PLUS             0x00080000
@@ -2198,6 +2213,11 @@ struct tg3 {
 #define TG3_FLG2_PARALLEL_DETECT       0x01000000
 #define TG3_FLG2_ICH_WORKAROUND                0x02000000
 #define TG3_FLG2_5780_CLASS            0x04000000
+#define TG3_FLG2_HW_TSO_2              0x08000000
+#define TG3_FLG2_HW_TSO                        (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
+#define TG3_FLG2_1SHOT_MSI             0x10000000
+#define TG3_FLG2_PHY_JITTER_BUG                0x20000000
+#define TG3_FLG2_NO_FWARE_REPORTED     0x40000000
 
        u32                             split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ                3
@@ -2247,6 +2267,8 @@ struct tg3 {
 #define PHY_ID_BCM5752                 0x60008100
 #define PHY_ID_BCM5714                 0x60008340
 #define PHY_ID_BCM5780                 0x60008350
+#define PHY_ID_BCM5755                 0xbc050cc0
+#define PHY_ID_BCM5787                 0xbc050ce0
 #define PHY_ID_BCM8002                 0x60010140
 #define PHY_ID_INVALID                 0xffffffff
 #define PHY_ID_REV_MASK                        0x0000000f
@@ -2258,6 +2280,7 @@ struct tg3 {
        u32                             led_ctrl;
 
        char                            board_part_number[24];
+       char                            fw_ver[16];
        u32                             nic_sram_data_cfg;
        u32                             pci_clock_ctrl;
        struct pci_dev                  *pdev_peer;
@@ -2271,7 +2294,8 @@ struct tg3 {
         (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
         (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
         (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
-        (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM8002)
+        (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
+        (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002)
 
        struct tg3_hw_stats             *hw_stats;
        dma_addr_t                      stats_mapping;
index ed96bf7..ab8b6b6 100644 (file)
 #define PCI_DEVICE_ID_TIGON3_5705M     0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
 #define PCI_DEVICE_ID_TIGON3_5714      0x1668
+#define PCI_DEVICE_ID_TIGON3_5714S     0x1669
 #define PCI_DEVICE_ID_TIGON3_5780      0x166a
 #define PCI_DEVICE_ID_TIGON3_5780S     0x166b
 #define PCI_DEVICE_ID_TIGON3_5705F     0x166e
+#define PCI_DEVICE_ID_TIGON3_5754M     0x1672
+#define PCI_DEVICE_ID_TIGON3_5755M     0x1673
 #define PCI_DEVICE_ID_TIGON3_5750      0x1676
 #define PCI_DEVICE_ID_TIGON3_5751      0x1677
 #define PCI_DEVICE_ID_TIGON3_5715      0x1678
+#define PCI_DEVICE_ID_TIGON3_5715S     0x1679
+#define PCI_DEVICE_ID_TIGON3_5754      0x167a
+#define PCI_DEVICE_ID_TIGON3_5755      0x167b
 #define PCI_DEVICE_ID_TIGON3_5750M     0x167c
 #define PCI_DEVICE_ID_TIGON3_5751M     0x167d
 #define PCI_DEVICE_ID_TIGON3_5751F     0x167e
+#define PCI_DEVICE_ID_TIGON3_5787M     0x1693
 #define PCI_DEVICE_ID_TIGON3_5782      0x1696
+#define PCI_DEVICE_ID_TIGON3_5787      0x169b
 #define PCI_DEVICE_ID_TIGON3_5788      0x169c
 #define PCI_DEVICE_ID_TIGON3_5789      0x169d
 #define PCI_DEVICE_ID_TIGON3_5702X     0x16a6