bnx2x: Add support for BCM57711 HW
[firefly-linux-kernel-4.4.55.git] / drivers / net / bnx2x_main.c
index efa942688f84feda87073377592279646465ba7b..90b54e4c5c3bb052a50841c0afc220cf97384edf 100644 (file)
@@ -1,4 +1,4 @@
-/* bnx2x.c: Broadcom Everest network driver.
+/* bnx2x_main.c: Broadcom Everest network driver.
  *
  * Copyright (c) 2007-2008 Broadcom Corporation
  *
  *
  */
 
-/* define this to make the driver freeze on error
- * to allow getting debug info
- * (you will need to reboot afterwards)
- */
-/*#define BNX2X_STOP_ON_ERROR*/
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/mii.h>
 #ifdef NETIF_F_HW_VLAN_TX
        #include <linux/if_vlan.h>
-       #define BCM_VLAN 1
 #endif
 #include <net/ip.h>
 #include <net/tcp.h>
 #include <net/checksum.h>
+#include <linux/version.h>
+#include <net/ip6_checksum.h>
 #include <linux/workqueue.h>
 #include <linux/crc32.h>
+#include <linux/crc32c.h>
 #include <linux/prefetch.h>
 #include <linux/zlib.h>
-#include <linux/version.h>
 #include <linux/io.h>
 
 #include "bnx2x_reg.h"
 
 #define DRV_MODULE_VERSION      "1.42.4"
 #define DRV_MODULE_RELDATE      "2008/4/9"
-#define BNX2X_BC_VER           0x040200
+#define BNX2X_BC_VER           0x040200
 
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT             (5*HZ)
+/* Time in jiffies before concluding the transmitter is hung */
+#define TX_TIMEOUT             (5*HZ)
 
 static char version[] __devinitdata =
-       "Broadcom NetXtreme II 5771X 10Gigabit Ethernet Driver "
+       "Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver "
        DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Eliezer Tamir");
@@ -83,20 +78,19 @@ MODULE_VERSION(DRV_MODULE_VERSION);
 
 static int use_inta;
 static int poll;
-static int onefunc;
-static int nomcp;
 static int debug;
+static int nomcp;
+static int load_count[3]; /* 0-common, 1-port0, 2-port1 */
 static int use_multi;
 
 module_param(use_inta, int, 0);
 module_param(poll, int, 0);
-module_param(onefunc, int, 0);
 module_param(debug, int, 0);
+module_param(nomcp, int, 0);
 MODULE_PARM_DESC(use_inta, "use INT#A instead of MSI-X");
 MODULE_PARM_DESC(poll, "use polling (for debug)");
-MODULE_PARM_DESC(onefunc, "enable only first function");
-MODULE_PARM_DESC(nomcp, "ignore management CPU (Implies onefunc)");
 MODULE_PARM_DESC(debug, "default debug msglevel");
+MODULE_PARM_DESC(nomcp, "ignore management CPU");
 
 #ifdef BNX2X_MULTI
 module_param(use_multi, int, 0);
@@ -105,18 +99,27 @@ MODULE_PARM_DESC(use_multi, "use per-CPU queues");
 
 enum bnx2x_board_type {
        BCM57710 = 0,
+       BCM57711 = 1,
+       BCM57711E = 2,
 };
 
-/* indexed by board_t, above */
+/* indexed by board_type, above */
 static struct {
        char *name;
 } board_info[] __devinitdata = {
-       { "Broadcom NetXtreme II BCM57710 XGb" }
+       { "Broadcom NetXtreme II BCM57710 XGb" },
+       { "Broadcom NetXtreme II BCM57711 XGb" },
+       { "Broadcom NetXtreme II BCM57711E XGb" }
 };
 
+
 static const struct pci_device_id bnx2x_pci_tbl[] = {
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57710,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57710 },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57711 },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57711E },
        { 0 }
 };
 
@@ -201,7 +204,8 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
 #else
                        DMAE_CMD_ENDIANITY_DW_SWAP |
 #endif
-                       (bp->port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0));
+                       (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+                       (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
        dmae->src_addr_lo = U64_LO(dma_addr);
        dmae->src_addr_hi = U64_HI(dma_addr);
        dmae->dst_addr_lo = dst_addr >> 2;
@@ -224,7 +228,7 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
 
        *wb_comp = 0;
 
-       bnx2x_post_dmae(bp, dmae, (bp->port)*MAX_DMAE_C_PER_PORT);
+       bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
 
        udelay(5);
 
@@ -277,7 +281,8 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
 #else
                        DMAE_CMD_ENDIANITY_DW_SWAP |
 #endif
-                       (bp->port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0));
+                       (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+                       (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
        dmae->src_addr_lo = src_addr >> 2;
        dmae->src_addr_hi = 0;
        dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
@@ -297,7 +302,7 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
 
        *wb_comp = 0;
 
-       bnx2x_post_dmae(bp, dmae, (bp->port)*MAX_DMAE_C_PER_PORT);
+       bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
 
        udelay(5);
 
@@ -345,47 +350,122 @@ static u64 bnx2x_wb_rd(struct bnx2x *bp, int reg)
 
 static int bnx2x_mc_assert(struct bnx2x *bp)
 {
-       int i, j, rc = 0;
        char last_idx;
-       const char storm[] = {"XTCU"};
-       const u32 intmem_base[] = {
-               BAR_XSTRORM_INTMEM,
-               BAR_TSTRORM_INTMEM,
-               BAR_CSTRORM_INTMEM,
-               BAR_USTRORM_INTMEM
-       };
-
-       /* Go through all instances of all SEMIs */
-       for (i = 0; i < 4; i++) {
-               last_idx = REG_RD8(bp, XSTORM_ASSERT_LIST_INDEX_OFFSET +
-                                  intmem_base[i]);
-               if (last_idx)
-                       BNX2X_LOG("DATA %cSTORM_ASSERT_LIST_INDEX 0x%x\n",
-                                 storm[i], last_idx);
-
-               /* print the asserts */
-               for (j = 0; j < STROM_ASSERT_ARRAY_SIZE; j++) {
-                       u32 row0, row1, row2, row3;
-
-                       row0 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) +
-                                     intmem_base[i]);
-                       row1 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) + 4 +
-                                     intmem_base[i]);
-                       row2 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) + 8 +
-                                     intmem_base[i]);
-                       row3 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) + 12 +
-                                     intmem_base[i]);
-
-                       if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
-                               BNX2X_LOG("DATA %cSTORM_ASSERT_INDEX 0x%x ="
-                                         " 0x%08x 0x%08x 0x%08x 0x%08x\n",
-                                         storm[i], j, row3, row2, row1, row0);
-                               rc++;
-                       } else {
-                               break;
-                       }
+       int i, rc = 0;
+       u32 row0, row1, row2, row3;
+
+       /* XSTORM */
+       last_idx = REG_RD8(bp, BAR_XSTRORM_INTMEM +
+                          XSTORM_ASSERT_LIST_INDEX_OFFSET);
+       if (last_idx)
+               BNX2X_ERR("XSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+       /* print the asserts */
+       for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+               row0 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+                             XSTORM_ASSERT_LIST_OFFSET(i));
+               row1 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+                             XSTORM_ASSERT_LIST_OFFSET(i) + 4);
+               row2 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+                             XSTORM_ASSERT_LIST_OFFSET(i) + 8);
+               row3 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+                             XSTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+               if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+                       BNX2X_ERR("XSTORM_ASSERT_INDEX 0x%x = 0x%08x"
+                                 " 0x%08x 0x%08x 0x%08x\n",
+                                 i, row3, row2, row1, row0);
+                       rc++;
+               } else {
+                       break;
+               }
+       }
+
+       /* TSTORM */
+       last_idx = REG_RD8(bp, BAR_TSTRORM_INTMEM +
+                          TSTORM_ASSERT_LIST_INDEX_OFFSET);
+       if (last_idx)
+               BNX2X_ERR("TSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+       /* print the asserts */
+       for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+               row0 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+                             TSTORM_ASSERT_LIST_OFFSET(i));
+               row1 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+                             TSTORM_ASSERT_LIST_OFFSET(i) + 4);
+               row2 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+                             TSTORM_ASSERT_LIST_OFFSET(i) + 8);
+               row3 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+                             TSTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+               if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+                       BNX2X_ERR("TSTORM_ASSERT_INDEX 0x%x = 0x%08x"
+                                 " 0x%08x 0x%08x 0x%08x\n",
+                                 i, row3, row2, row1, row0);
+                       rc++;
+               } else {
+                       break;
+               }
+       }
+
+       /* CSTORM */
+       last_idx = REG_RD8(bp, BAR_CSTRORM_INTMEM +
+                          CSTORM_ASSERT_LIST_INDEX_OFFSET);
+       if (last_idx)
+               BNX2X_ERR("CSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+       /* print the asserts */
+       for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+               row0 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+                             CSTORM_ASSERT_LIST_OFFSET(i));
+               row1 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+                             CSTORM_ASSERT_LIST_OFFSET(i) + 4);
+               row2 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+                             CSTORM_ASSERT_LIST_OFFSET(i) + 8);
+               row3 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+                             CSTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+               if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+                       BNX2X_ERR("CSTORM_ASSERT_INDEX 0x%x = 0x%08x"
+                                 " 0x%08x 0x%08x 0x%08x\n",
+                                 i, row3, row2, row1, row0);
+                       rc++;
+               } else {
+                       break;
+               }
+       }
+
+       /* USTORM */
+       last_idx = REG_RD8(bp, BAR_USTRORM_INTMEM +
+                          USTORM_ASSERT_LIST_INDEX_OFFSET);
+       if (last_idx)
+               BNX2X_ERR("USTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+       /* print the asserts */
+       for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+               row0 = REG_RD(bp, BAR_USTRORM_INTMEM +
+                             USTORM_ASSERT_LIST_OFFSET(i));
+               row1 = REG_RD(bp, BAR_USTRORM_INTMEM +
+                             USTORM_ASSERT_LIST_OFFSET(i) + 4);
+               row2 = REG_RD(bp, BAR_USTRORM_INTMEM +
+                             USTORM_ASSERT_LIST_OFFSET(i) + 8);
+               row3 = REG_RD(bp, BAR_USTRORM_INTMEM +
+                             USTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+               if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+                       BNX2X_ERR("USTORM_ASSERT_INDEX 0x%x = 0x%08x"
+                                 " 0x%08x 0x%08x 0x%08x\n",
+                                 i, row3, row2, row1, row0);
+                       rc++;
+               } else {
+                       break;
                }
        }
+
        return rc;
 }
 
@@ -428,14 +508,16 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
                struct eth_tx_db_data *hw_prods = fp->hw_tx_prods;
 
                BNX2X_ERR("queue[%d]: tx_pkt_prod(%x)  tx_pkt_cons(%x)"
-                         "  tx_bd_prod(%x)  tx_bd_cons(%x)  *tx_cons_sb(%x)"
-                         "  *rx_cons_sb(%x)  rx_comp_prod(%x)"
-                         "  rx_comp_cons(%x)  fp_c_idx(%x)  fp_u_idx(%x)"
-                         "  bd data(%x,%x)\n",
+                         "  tx_bd_prod(%x)  tx_bd_cons(%x)  *tx_cons_sb(%x)\n",
                          i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
-                         fp->tx_bd_cons, *fp->tx_cons_sb, *fp->rx_cons_sb,
-                         fp->rx_comp_prod, fp->rx_comp_cons, fp->fp_c_idx,
-                         fp->fp_u_idx, hw_prods->packets_prod,
+                         fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
+               BNX2X_ERR("          rx_comp_prod(%x)  rx_comp_cons(%x)"
+                         "  *rx_cons_sb(%x)\n",
+                         fp->rx_comp_prod, fp->rx_comp_cons,
+                         le16_to_cpu(*fp->rx_cons_sb));
+               BNX2X_ERR("          fp_c_idx(%x)  fp_u_idx(%x)"
+                         "  bd data(%x,%x)\n",
+                         fp->fp_c_idx, fp->fp_u_idx, hw_prods->packets_prod,
                          hw_prods->bds_prod);
 
                start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
@@ -463,7 +545,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
                        struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j];
 
                        BNX2X_ERR("rx_bd[%x]=[%x:%x]  sw_bd=[%p]\n",
-                                 j, rx_bd[0], rx_bd[1], sw_bd->skb);
+                                 j, rx_bd[1], rx_bd[0], sw_bd->skb);
                }
 
                start = RCQ_BD(fp->rx_comp_cons - 10);
@@ -482,7 +564,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
                  bp->def_c_idx, bp->def_u_idx, bp->def_x_idx, bp->def_t_idx,
                  bp->def_att_idx, bp->attn_state, bp->spq_prod_idx);
 
-
+       bnx2x_fw_dump(bp);
        bnx2x_mc_assert(bp);
        BNX2X_ERR("end crash dump -----------------\n");
 
@@ -492,7 +574,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
 
 static void bnx2x_int_enable(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
        u32 val = REG_RD(bp, addr);
        int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
@@ -507,7 +589,6 @@ static void bnx2x_int_enable(struct bnx2x *bp)
                        HC_CONFIG_0_REG_INT_LINE_EN_0 |
                        HC_CONFIG_0_REG_ATTN_BIT_EN_0);
 
-               /* Errata A0.158 workaround */
                DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)  MSI-X %d\n",
                   val, port, addr, msix);
 
@@ -520,11 +601,25 @@ static void bnx2x_int_enable(struct bnx2x *bp)
           val, port, addr, msix);
 
        REG_WR(bp, addr, val);
+
+       if (CHIP_IS_E1H(bp)) {
+               /* init leading/trailing edge */
+               if (IS_E1HMF(bp)) {
+                       val = (0xfe0f | (1 << (BP_E1HVN(bp) + 4)));
+                       if (bp->port.pmf)
+                               /* enable nig attention */
+                               val |= 0x0100;
+               } else
+                       val = 0xffff;
+
+               REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
+               REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+       }
 }
 
 static void bnx2x_int_disable(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
        u32 val = REG_RD(bp, addr);
 
@@ -543,10 +638,10 @@ static void bnx2x_int_disable(struct bnx2x *bp)
 
 static void bnx2x_int_disable_sync(struct bnx2x *bp)
 {
-
        int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
        int i;
 
+       /* disable interrupt handling */
        atomic_inc(&bp->intr_sem);
        /* prevent the HW from sending interrupts */
        bnx2x_int_disable(bp);
@@ -563,30 +658,29 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp)
 
        /* make sure sp_task is not running */
        cancel_work_sync(&bp->sp_task);
-
 }
 
-/* fast path code */
+/* fast path */
 
 /*
- * general service functions
+ * General service functions
  */
 
-static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 id,
+static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
                                u8 storm, u16 index, u8 op, u8 update)
 {
-       u32 igu_addr = (IGU_ADDR_INT_ACK + IGU_PORT_BASE * bp->port) * 8;
+       u32 igu_addr = (IGU_ADDR_INT_ACK + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
        struct igu_ack_register igu_ack;
 
        igu_ack.status_block_index = index;
        igu_ack.sb_id_and_flags =
-                       ((id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
+                       ((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
                         (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) |
                         (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) |
                         (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT));
 
-/*      DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
-          (*(u32 *)&igu_ack), BAR_IGU_INTMEM + igu_addr); */
+       DP(BNX2X_MSG_OFF, "write 0x%08x to IGU addr 0x%x\n",
+          (*(u32 *)&igu_ack), BAR_IGU_INTMEM + igu_addr);
        REG_WR(bp, BAR_IGU_INTMEM + igu_addr, (*(u32 *)&igu_ack));
 }
 
@@ -614,8 +708,9 @@ static inline int bnx2x_has_work(struct bnx2x_fastpath *fp)
        if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
                rx_cons_sb++;
 
-       if ((rx_cons_sb != fp->rx_comp_cons) ||
-           (le16_to_cpu(*fp->tx_cons_sb) != fp->tx_pkt_cons))
+       if ((fp->rx_comp_cons != rx_cons_sb) ||
+           (fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) ||
+           (fp->tx_pkt_prod != fp->tx_pkt_cons))
                return 1;
 
        return 0;
@@ -623,11 +718,11 @@ static inline int bnx2x_has_work(struct bnx2x_fastpath *fp)
 
 static u16 bnx2x_ack_int(struct bnx2x *bp)
 {
-       u32 igu_addr = (IGU_ADDR_SIMD_MASK + IGU_PORT_BASE * bp->port) * 8;
+       u32 igu_addr = (IGU_ADDR_SIMD_MASK + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
        u32 result = REG_RD(bp, BAR_IGU_INTMEM + igu_addr);
 
-/*      DP(NETIF_MSG_INTR, "read 0x%08x from IGU addr 0x%x\n",
-          result, BAR_IGU_INTMEM + igu_addr); */
+       DP(BNX2X_MSG_OFF, "read 0x%08x from IGU addr 0x%x\n",
+          result, BAR_IGU_INTMEM + igu_addr);
 
 #ifdef IGU_DEBUG
 #warning IGU_DEBUG active
@@ -653,7 +748,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx];
        struct eth_tx_bd *tx_bd;
        struct sk_buff *skb = tx_buf->skb;
-       u16 bd_idx = tx_buf->first_bd;
+       u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
        int nbd;
 
        DP(BNX2X_MSG_OFF, "pkt_idx %d  buff @(%p)->skb %p\n",
@@ -666,9 +761,10 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                         BD_UNMAP_LEN(tx_bd), PCI_DMA_TODEVICE);
 
        nbd = le16_to_cpu(tx_bd->nbd) - 1;
+       new_cons = nbd + tx_buf->first_bd;
 #ifdef BNX2X_STOP_ON_ERROR
        if (nbd > (MAX_SKB_FRAGS + 2)) {
-               BNX2X_ERR("bad nbd!\n");
+               BNX2X_ERR("BAD nbd!\n");
                bnx2x_panic();
        }
 #endif
@@ -708,32 +804,30 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        tx_buf->first_bd = 0;
        tx_buf->skb = NULL;
 
-       return bd_idx;
+       return new_cons;
 }
 
-static inline u32 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
+static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
 {
-       u16 used;
-       u32 prod;
-       u32 cons;
+       s16 used;
+       u16 prod;
+       u16 cons;
 
-       /* Tell compiler that prod and cons can change */
-       barrier();
+       barrier(); /* Tell compiler that prod and cons can change */
        prod = fp->tx_bd_prod;
        cons = fp->tx_bd_cons;
 
-       used = (NUM_TX_BD - NUM_TX_RINGS + prod - cons +
-               (cons / TX_DESC_CNT) - (prod / TX_DESC_CNT));
-
-       if (prod >= cons) {
-               /* used = prod - cons - prod/size + cons/size */
-               used -= NUM_TX_BD - NUM_TX_RINGS;
-       }
+       /* NUM_TX_RINGS = number of "next-page" entries
+          It will be used as a threshold */
+       used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
 
+#ifdef BNX2X_STOP_ON_ERROR
+       BUG_TRAP(used >= 0);
        BUG_TRAP(used <= fp->bp->tx_ring_size);
        BUG_TRAP((fp->bp->tx_ring_size - used) <= MAX_TX_AVAIL);
+#endif
 
-       return (fp->bp->tx_ring_size - used);
+       return (s16)(fp->bp->tx_ring_size) - used;
 }
 
 static void bnx2x_tx_int(struct bnx2x_fastpath *fp, int work)
@@ -757,10 +851,10 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp, int work)
 
                /* prefetch(bp->tx_buf_ring[pkt_cons].skb); */
 
-               DP(NETIF_MSG_TX_DONE, "hw_cons %u  sw_cons %u  pkt_cons %d\n",
+               DP(NETIF_MSG_TX_DONE, "hw_cons %u  sw_cons %u  pkt_cons %u\n",
                   hw_cons, sw_cons, pkt_cons);
 
-/*             if (NEXT_TX_IDX(sw_cons) != hw_cons) {
+/*             if (NEXT_TX_IDX(sw_cons) != hw_cons) {
                        rmb();
                        prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb);
                }
@@ -793,7 +887,6 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp, int work)
                        netif_wake_queue(bp->dev);
 
                netif_tx_unlock(bp->dev);
-
        }
 }
 
@@ -804,13 +897,14 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
        int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data);
        int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data);
 
-       DP(NETIF_MSG_RX_STATUS,
+       DP(BNX2X_MSG_SP,
           "fp %d  cid %d  got ramrod #%d  state is %x  type is %d\n",
-          fp->index, cid, command, bp->state, rr_cqe->ramrod_cqe.type);
+          FP_IDX(fp), cid, command, bp->state,
+          rr_cqe->ramrod_cqe.ramrod_type);
 
        bp->spq_left++;
 
-       if (fp->index) {
+       if (FP_IDX(fp)) {
                switch (command | fp->state) {
                case (RAMROD_CMD_ID_ETH_CLIENT_SETUP |
                                                BNX2X_FP_STATE_OPENING):
@@ -826,10 +920,11 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
                        break;
 
                default:
-                       BNX2X_ERR("unexpected MC reply(%d)  state is %x\n",
-                                 command, fp->state);
+                       BNX2X_ERR("unexpected MC reply (%d)  "
+                                 "fp->state is %x\n", command, fp->state);
+                       break;
                }
-               mb(); /* force bnx2x_wait_ramrod to see the change */
+               mb(); /* force bnx2x_wait_ramrod() to see the change */
                return;
        }
 
@@ -846,25 +941,25 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
                break;
 
        case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_CLOSING_WAIT4_HALT):
-               DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n",
-                  cid);
+               DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n", cid);
                bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED;
                break;
 
        case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN):
+       case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG):
                DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
                break;
 
        case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT):
-               DP(NETIF_MSG_IFUP, "got (un)set mac ramrod\n");
+               DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
                break;
 
        default:
-               BNX2X_ERR("unexpected ramrod (%d)  state is %x\n",
+               BNX2X_ERR("unexpected MC reply (%d)  bp->state is %x\n",
                          command, bp->state);
+               break;
        }
-
-       mb(); /* force bnx2x_wait_ramrod to see the change */
+       mb(); /* force bnx2x_wait_ramrod() to see the change */
 }
 
 static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
@@ -882,7 +977,6 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
        mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
                                 PCI_DMA_FROMDEVICE);
        if (unlikely(dma_mapping_error(mapping))) {
-
                dev_kfree_skb(skb);
                return -ENOMEM;
        }
@@ -924,7 +1018,7 @@ static void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
 static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 {
        struct bnx2x *bp = fp->bp;
-       u16 bd_cons, bd_prod, comp_ring_cons;
+       u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons;
        u16 hw_comp_cons, sw_comp_cons, sw_comp_prod;
        int rx_pkt = 0;
 
@@ -933,12 +1027,15 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                return 0;
 #endif
 
+       /* CQ "next element" is of the size of the regular element,
+          that's why it's ok here */
        hw_comp_cons = le16_to_cpu(*fp->rx_cons_sb);
        if ((hw_comp_cons & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
                hw_comp_cons++;
 
        bd_cons = fp->rx_bd_cons;
        bd_prod = fp->rx_bd_prod;
+       bd_prod_fw = bd_prod;
        sw_comp_cons = fp->rx_comp_cons;
        sw_comp_prod = fp->rx_comp_prod;
 
@@ -949,34 +1046,31 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 
        DP(NETIF_MSG_RX_STATUS,
           "queue[%d]:  hw_comp_cons %u  sw_comp_cons %u\n",
-          fp->index, hw_comp_cons, sw_comp_cons);
+          FP_IDX(fp), hw_comp_cons, sw_comp_cons);
 
        while (sw_comp_cons != hw_comp_cons) {
-               unsigned int len, pad;
-               struct sw_rx_bd *rx_buf;
+               struct sw_rx_bd *rx_buf = NULL;
                struct sk_buff *skb;
                union eth_rx_cqe *cqe;
+               u8 cqe_fp_flags;
+               u16 len, pad;
 
                comp_ring_cons = RCQ_BD(sw_comp_cons);
                bd_prod = RX_BD(bd_prod);
                bd_cons = RX_BD(bd_cons);
 
                cqe = &fp->rx_comp_ring[comp_ring_cons];
+               cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
 
-               DP(NETIF_MSG_RX_STATUS, "hw_comp_cons %u  sw_comp_cons %u"
-                  "  comp_ring (%u)  bd_ring (%u,%u)\n",
-                  hw_comp_cons, sw_comp_cons,
-                  comp_ring_cons, bd_prod, bd_cons);
                DP(NETIF_MSG_RX_STATUS, "CQE type %x  err %x  status %x"
-                  "  queue %x  vlan %x  len %x\n",
-                  cqe->fast_path_cqe.type,
-                  cqe->fast_path_cqe.error_type_flags,
-                  cqe->fast_path_cqe.status_flags,
+                  "  queue %x  vlan %x  len %u\n", CQE_TYPE(cqe_fp_flags),
+                  cqe_fp_flags, cqe->fast_path_cqe.status_flags,
                   cqe->fast_path_cqe.rss_hash_result,
-                  cqe->fast_path_cqe.vlan_tag, cqe->fast_path_cqe.pkt_len);
+                  le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
+                  le16_to_cpu(cqe->fast_path_cqe.pkt_len));
 
                /* is this a slowpath msg? */
-               if (unlikely(cqe->fast_path_cqe.type)) {
+               if (unlikely(CQE_TYPE(cqe_fp_flags))) {
                        bnx2x_sp_event(fp, cqe);
                        goto next_cqe;
 
@@ -984,7 +1078,6 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                } else {
                        rx_buf = &fp->rx_buf_ring[bd_cons];
                        skb = rx_buf->skb;
-
                        len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
                        pad = cqe->fast_path_cqe.placement_offset;
 
@@ -996,13 +1089,11 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                        prefetch(((char *)(skb)) + 128);
 
                        /* is this an error packet? */
-                       if (unlikely(cqe->fast_path_cqe.error_type_flags &
-                                                       ETH_RX_ERROR_FALGS)) {
+                       if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
                        /* do we sometimes forward error packets anyway? */
                                DP(NETIF_MSG_RX_ERR,
-                                  "ERROR flags(%u) Rx packet(%u)\n",
-                                  cqe->fast_path_cqe.error_type_flags,
-                                  sw_comp_cons);
+                                  "ERROR  flags %x  rx packet %u\n",
+                                  cqe_fp_flags, sw_comp_cons);
                                /* TBD make sure MC counts this as a drop */
                                goto reuse_rx;
                        }
@@ -1018,7 +1109,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                                                           len + pad);
                                if (new_skb == NULL) {
                                        DP(NETIF_MSG_RX_ERR,
-                                          "ERROR packet dropped "
+                                          "ERROR  packet dropped "
                                           "because of alloc failure\n");
                                        /* TBD count this as a drop? */
                                        goto reuse_rx;
@@ -1044,7 +1135,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 
                        } else {
                                DP(NETIF_MSG_RX_ERR,
-                                  "ERROR packet dropped because "
+                                  "ERROR  packet dropped because "
                                   "of alloc failure\n");
 reuse_rx:
                                bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
@@ -1061,14 +1152,14 @@ reuse_rx:
                }
 
 #ifdef BCM_VLAN
-               if ((le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags)
-                               & PARSING_FLAGS_NUMBER_OF_NESTED_VLANS)
-                   && (bp->vlgrp != NULL))
+               if ((bp->vlgrp != NULL) &&
+                   (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
+                    PARSING_FLAGS_VLAN))
                        vlan_hwaccel_receive_skb(skb, bp->vlgrp,
                                le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
                else
 #endif
-               netif_receive_skb(skb);
+                       netif_receive_skb(skb);
 
                bp->dev->last_rx = jiffies;
 
@@ -1077,22 +1168,25 @@ next_rx:
 
                bd_cons = NEXT_RX_IDX(bd_cons);
                bd_prod = NEXT_RX_IDX(bd_prod);
+               bd_prod_fw = NEXT_RX_IDX(bd_prod_fw);
+               rx_pkt++;
 next_cqe:
                sw_comp_prod = NEXT_RCQ_IDX(sw_comp_prod);
                sw_comp_cons = NEXT_RCQ_IDX(sw_comp_cons);
-               rx_pkt++;
 
-               if ((rx_pkt == budget))
+               if (rx_pkt == budget)
                        break;
        } /* while */
 
        fp->rx_bd_cons = bd_cons;
-       fp->rx_bd_prod = bd_prod;
+       fp->rx_bd_prod = bd_prod_fw;
        fp->rx_comp_cons = sw_comp_cons;
        fp->rx_comp_prod = sw_comp_prod;
 
        REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_RCQ_PROD_OFFSET(bp->port, fp->index), sw_comp_prod);
+               TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)),
+               sw_comp_prod);
+
 
        mmiowb(); /* keep prod updates ordered */
 
@@ -1107,10 +1201,11 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
        struct bnx2x_fastpath *fp = fp_cookie;
        struct bnx2x *bp = fp->bp;
        struct net_device *dev = bp->dev;
-       int index = fp->index;
+       int index = FP_IDX(fp);
 
-       DP(NETIF_MSG_INTR, "got an msix interrupt on [%d]\n", index);
-       bnx2x_ack_sb(bp, index, USTORM_ID, 0, IGU_INT_DISABLE, 0);
+       DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n",
+          index, FP_SB_ID(fp));
+       bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID, 0, IGU_INT_DISABLE, 0);
 
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic))
@@ -1123,6 +1218,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
        prefetch(&fp->status_blk->u_status_block.status_block_index);
 
        netif_rx_schedule(dev, &bnx2x_fp(bp, index, napi));
+
        return IRQ_HANDLED;
 }
 
@@ -1131,26 +1227,28 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
        struct net_device *dev = dev_instance;
        struct bnx2x *bp = netdev_priv(dev);
        u16 status = bnx2x_ack_int(bp);
+       u16 mask;
 
+       /* Return here if interrupt is shared and it's not for us */
        if (unlikely(status == 0)) {
                DP(NETIF_MSG_INTR, "not our interrupt!\n");
                return IRQ_NONE;
        }
-
-       DP(NETIF_MSG_INTR, "got an interrupt status is %u\n", status);
+       DP(NETIF_MSG_INTR, "got an interrupt  status %u\n", status);
 
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic))
                return IRQ_HANDLED;
 #endif
 
-       /* Return here if interrupt is shared and is disabled */
+       /* Return here if interrupt is disabled */
        if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
                DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
                return IRQ_HANDLED;
        }
 
-       if (status & 0x2) {
+       mask = 0x2 << bp->fp[0].sb_id;
+       if (status & mask) {
                struct bnx2x_fastpath *fp = &bp->fp[0];
 
                prefetch(fp->rx_cons_sb);
@@ -1160,13 +1258,11 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 
                netif_rx_schedule(dev, &bnx2x_fp(bp, 0, napi));
 
-               status &= ~0x2;
-               if (!status)
-                       return IRQ_HANDLED;
+               status &= ~mask;
        }
 
-       if (unlikely(status & 0x1)) {
 
+       if (unlikely(status & 0x1)) {
                schedule_work(&bp->sp_task);
 
                status &= ~0x1;
@@ -1174,8 +1270,9 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
                        return IRQ_HANDLED;
        }
 
-       DP(NETIF_MSG_INTR, "got an unknown interrupt! (status is %u)\n",
-          status);
+       if (status)
+               DP(NETIF_MSG_INTR, "got an unknown interrupt! (status %u)\n",
+                  status);
 
        return IRQ_HANDLED;
 }
@@ -1193,7 +1290,7 @@ static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource)
 {
        u32 lock_status;
        u32 resource_bit = (1 << resource);
-       u8 port = bp->port;
+       u8 port = BP_PORT(bp);
        int cnt;
 
        /* Validating that the resource is within range */
@@ -1231,7 +1328,7 @@ static int bnx2x_hw_unlock(struct bnx2x *bp, u32 resource)
 {
        u32 lock_status;
        u32 resource_bit = (1 << resource);
-       u8 port = bp->port;
+       u8 port = BP_PORT(bp);
 
        /* Validating that the resource is within range */
        if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
@@ -1258,7 +1355,7 @@ static void bnx2x_phy_hw_lock(struct bnx2x *bp)
 {
        u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
 
-       mutex_lock(&bp->phy_mutex);
+       mutex_lock(&bp->port.phy_mutex);
 
        if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) ||
            (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))
@@ -1273,14 +1370,14 @@ static void bnx2x_phy_hw_unlock(struct bnx2x *bp)
            (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))
                bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO);
 
-       mutex_unlock(&bp->phy_mutex);
+       mutex_unlock(&bp->port.phy_mutex);
 }
 
 int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode)
 {
        /* The GPIO should be swapped if swap register is set and active */
        int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) &&
-                        REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ bp->port;
+                        REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ BP_PORT(bp);
        int gpio_shift = gpio_num +
                        (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
        u32 gpio_mask = (1 << gpio_shift);
@@ -1379,18 +1476,18 @@ static void bnx2x_calc_fc_adv(struct bnx2x *bp)
 {
        switch (bp->link_vars.ieee_fc) {
        case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
-               bp->advertising &= ~(ADVERTISED_Asym_Pause |
+               bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
                                          ADVERTISED_Pause);
                break;
        case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH:
-               bp->advertising |= (ADVERTISED_Asym_Pause |
+               bp->port.advertising |= (ADVERTISED_Asym_Pause |
                                         ADVERTISED_Pause);
                break;
        case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC:
-               bp->advertising |= ADVERTISED_Asym_Pause;
+               bp->port.advertising |= ADVERTISED_Asym_Pause;
                break;
        default:
-               bp->advertising &= ~(ADVERTISED_Asym_Pause |
+               bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
                                          ADVERTISED_Pause);
                break;
        }
@@ -1443,6 +1540,7 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp)
                bnx2x_link_report(bp);
 
        bnx2x_calc_fc_adv(bp);
+
        return rc;
 }
 
@@ -1473,15 +1571,261 @@ static u8 bnx2x_link_test(struct bnx2x *bp)
        return rc;
 }
 
+/* Calculates the sum of vn_min_rates.
+   It's needed for further normalizing of the min_rates.
+
+   Returns:
+     sum of vn_min_rates
+       or
+     0 - if all the min_rates are 0.
+     In the later case fainess algorithm should be deactivated.
+     If not all min_rates are zero then those that are zeroes will
+     be set to 1.
+ */
+static u32 bnx2x_calc_vn_wsum(struct bnx2x *bp)
+{
+       int i, port = BP_PORT(bp);
+       u32 wsum = 0;
+       int all_zero = 1;
+
+       for (i = 0; i < E1HVN_MAX; i++) {
+               u32 vn_cfg =
+                       SHMEM_RD(bp, mf_cfg.func_mf_config[2*i + port].config);
+               u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
+                                    FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
+               if (!(vn_cfg & FUNC_MF_CFG_FUNC_HIDE)) {
+                       /* If min rate is zero - set it to 1 */
+                       if (!vn_min_rate)
+                               vn_min_rate = DEF_MIN_RATE;
+                       else
+                               all_zero = 0;
+
+                       wsum += vn_min_rate;
+               }
+       }
+
+       /* ... only if all min rates are zeros - disable FAIRNESS */
+       if (all_zero)
+               return 0;
+
+       return wsum;
+}
+
+static void bnx2x_init_port_minmax(struct bnx2x *bp,
+                                  int en_fness,
+                                  u16 port_rate,
+                                  struct cmng_struct_per_port *m_cmng_port)
+{
+       u32 r_param = port_rate / 8;
+       int port = BP_PORT(bp);
+       int i;
+
+       memset(m_cmng_port, 0, sizeof(struct cmng_struct_per_port));
+
+       /* Enable minmax only if we are in e1hmf mode */
+       if (IS_E1HMF(bp)) {
+               u32 fair_periodic_timeout_usec;
+               u32 t_fair;
+
+               /* Enable rate shaping and fairness */
+               m_cmng_port->flags.cmng_vn_enable = 1;
+               m_cmng_port->flags.fairness_enable = en_fness ? 1 : 0;
+               m_cmng_port->flags.rate_shaping_enable = 1;
+
+               if (!en_fness)
+                       DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
+                          "  fairness will be disabled\n");
+
+               /* 100 usec in SDM ticks = 25 since each tick is 4 usec */
+               m_cmng_port->rs_vars.rs_periodic_timeout =
+                                               RS_PERIODIC_TIMEOUT_USEC / 4;
+
+               /* this is the threshold below which no timer arming will occur
+                  1.25 coefficient is for the threshold to be a little bigger
+                  than the real time, to compensate for timer in-accuracy */
+               m_cmng_port->rs_vars.rs_threshold =
+                               (RS_PERIODIC_TIMEOUT_USEC * r_param * 5) / 4;
+
+               /* resolution of fairness timer */
+               fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
+               /* for 10G it is 1000usec. for 1G it is 10000usec. */
+               t_fair = T_FAIR_COEF / port_rate;
+
+               /* this is the threshold below which we won't arm
+                  the timer anymore */
+               m_cmng_port->fair_vars.fair_threshold = QM_ARB_BYTES;
+
+               /* we multiply by 1e3/8 to get bytes/msec.
+                  We don't want the credits to pass a credit
+                  of the T_FAIR*FAIR_MEM (algorithm resolution) */
+               m_cmng_port->fair_vars.upper_bound =
+                                               r_param * t_fair * FAIR_MEM;
+               /* since each tick is 4 usec */
+               m_cmng_port->fair_vars.fairness_timeout =
+                                               fair_periodic_timeout_usec / 4;
+
+       } else {
+               /* Disable rate shaping and fairness */
+               m_cmng_port->flags.cmng_vn_enable = 0;
+               m_cmng_port->flags.fairness_enable = 0;
+               m_cmng_port->flags.rate_shaping_enable = 0;
+
+               DP(NETIF_MSG_IFUP,
+                  "Single function mode  minmax will be disabled\n");
+       }
+
+       /* Store it to internal memory */
+       for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
+               REG_WR(bp, BAR_XSTRORM_INTMEM +
+                      XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i * 4,
+                      ((u32 *)(m_cmng_port))[i]);
+}
+
+static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func,
+                                  u32 wsum, u16 port_rate,
+                                struct cmng_struct_per_port *m_cmng_port)
+{
+       struct rate_shaping_vars_per_vn m_rs_vn;
+       struct fairness_vars_per_vn m_fair_vn;
+       u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+       u16 vn_min_rate, vn_max_rate;
+       int i;
+
+       /* If function is hidden - set min and max to zeroes */
+       if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) {
+               vn_min_rate = 0;
+               vn_max_rate = 0;
+
+       } else {
+               vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
+                               FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
+               /* If FAIRNESS is enabled (not all min rates are zeroes) and
+                  if current min rate is zero - set it to 1.
+                  This is a requirment of the algorithm. */
+               if ((vn_min_rate == 0) && wsum)
+                       vn_min_rate = DEF_MIN_RATE;
+               vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
+                               FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+       }
+
+       DP(NETIF_MSG_IFUP, "func %d: vn_min_rate=%d  vn_max_rate=%d  "
+          "wsum=%d\n", func, vn_min_rate, vn_max_rate, wsum);
+
+       memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn));
+       memset(&m_fair_vn, 0, sizeof(struct fairness_vars_per_vn));
+
+       /* global vn counter - maximal Mbps for this vn */
+       m_rs_vn.vn_counter.rate = vn_max_rate;
+
+       /* quota - number of bytes transmitted in this period */
+       m_rs_vn.vn_counter.quota =
+                               (vn_max_rate * RS_PERIODIC_TIMEOUT_USEC) / 8;
+
+#ifdef BNX2X_PER_PROT_QOS
+       /* per protocol counter */
+       for (protocol = 0; protocol < NUM_OF_PROTOCOLS; protocol++) {
+               /* maximal Mbps for this protocol */
+               m_rs_vn.protocol_counters[protocol].rate =
+                                               protocol_max_rate[protocol];
+               /* the quota in each timer period -
+                  number of bytes transmitted in this period */
+               m_rs_vn.protocol_counters[protocol].quota =
+                       (u32)(rs_periodic_timeout_usec *
+                         ((double)m_rs_vn.
+                                  protocol_counters[protocol].rate/8));
+       }
+#endif
+
+       if (wsum) {
+               /* credit for each period of the fairness algorithm:
+                  number of bytes in T_FAIR (the vn share the port rate).
+                  wsum should not be larger than 10000, thus
+                  T_FAIR_COEF / (8 * wsum) will always be grater than zero */
+               m_fair_vn.vn_credit_delta =
+                       max((u64)(vn_min_rate * (T_FAIR_COEF / (8 * wsum))),
+                           (u64)(m_cmng_port->fair_vars.fair_threshold * 2));
+               DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta=%d\n",
+                  m_fair_vn.vn_credit_delta);
+       }
+
+#ifdef BNX2X_PER_PROT_QOS
+       do {
+               u32 protocolWeightSum = 0;
+
+               for (protocol = 0; protocol < NUM_OF_PROTOCOLS; protocol++)
+                       protocolWeightSum +=
+                                       drvInit.protocol_min_rate[protocol];
+               /* per protocol counter -
+                  NOT NEEDED IF NO PER-PROTOCOL CONGESTION MANAGEMENT */
+               if (protocolWeightSum > 0) {
+                       for (protocol = 0;
+                            protocol < NUM_OF_PROTOCOLS; protocol++)
+                               /* credit for each period of the
+                                  fairness algorithm - number of bytes in
+                                  T_FAIR (the protocol share the vn rate) */
+                               m_fair_vn.protocol_credit_delta[protocol] =
+                                       (u32)((vn_min_rate / 8) * t_fair *
+                                       protocol_min_rate / protocolWeightSum);
+               }
+       } while (0);
+#endif
+
+       /* Store it to internal memory */
+       for (i = 0; i < sizeof(struct rate_shaping_vars_per_vn)/4; i++)
+               REG_WR(bp, BAR_XSTRORM_INTMEM +
+                      XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func) + i * 4,
+                      ((u32 *)(&m_rs_vn))[i]);
+
+       for (i = 0; i < sizeof(struct fairness_vars_per_vn)/4; i++)
+               REG_WR(bp, BAR_XSTRORM_INTMEM +
+                      XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func) + i * 4,
+                      ((u32 *)(&m_fair_vn))[i]);
+}
+
 /* This function is called upon link interrupt */
 static void bnx2x_link_attn(struct bnx2x *bp)
 {
+       int vn;
+
        bnx2x_phy_hw_lock(bp);
        bnx2x_link_update(&bp->link_params, &bp->link_vars);
        bnx2x_phy_hw_unlock(bp);
 
        /* indicate link status */
        bnx2x_link_report(bp);
+
+       if (IS_E1HMF(bp)) {
+               int func;
+
+               for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+                       if (vn == BP_E1HVN(bp))
+                               continue;
+
+                       func = ((vn << 1) | BP_PORT(bp));
+
+                       /* Set the attention towards other drivers
+                          on the same port */
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
+                              (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
+               }
+       }
+
+       if (CHIP_IS_E1H(bp) && (bp->link_vars.line_speed > 0)) {
+               struct cmng_struct_per_port m_cmng_port;
+               u32 wsum;
+               int port = BP_PORT(bp);
+
+               /* Init RATE SHAPING and FAIRNESS contexts */
+               wsum = bnx2x_calc_vn_wsum(bp);
+               bnx2x_init_port_minmax(bp, (int)wsum,
+                                       bp->link_vars.line_speed,
+                                       &m_cmng_port);
+               if (IS_E1HMF(bp))
+                       for (vn = VN_0; vn < E1HVN_MAX; vn++)
+                               bnx2x_init_vn_minmax(bp, 2*vn + port,
+                                       wsum, bp->link_vars.line_speed,
+                                                    &m_cmng_port);
+       }
 }
 
 static void bnx2x__link_status_update(struct bnx2x *bp)
@@ -1495,6 +1839,20 @@ static void bnx2x__link_status_update(struct bnx2x *bp)
        bnx2x_link_report(bp);
 }
 
+static void bnx2x_pmf_update(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+       u32 val;
+
+       bp->port.pmf = 1;
+       DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+
+       /* enable nig attention */
+       val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
+       REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
+       REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+}
+
 /* end of Link */
 
 /* slow path */
@@ -1507,10 +1865,10 @@ static void bnx2x__link_status_update(struct bnx2x *bp)
 static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
                         u32 data_hi, u32 data_lo, int common)
 {
-       int port = bp->port;
+       int func = BP_FUNC(bp);
 
-       DP(NETIF_MSG_TIMER,
-          "spe (%x:%x)  command %d  hw_cid %x  data (%x:%x)  left %x\n",
+       DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
+          "SPQE (%x:%x)  command %d  hw_cid %x  data (%x:%x)  left %x\n",
           (u32)U64_HI(bp->spq_mapping), (u32)(U64_LO(bp->spq_mapping) +
           (void *)bp->spq_prod_bd - (void *)bp->spq), command,
           HW_CID(bp, cid), data_hi, data_lo, bp->spq_left);
@@ -1520,11 +1878,11 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
                return -EIO;
 #endif
 
-       spin_lock(&bp->spq_lock);
+       spin_lock_bh(&bp->spq_lock);
 
        if (!bp->spq_left) {
                BNX2X_ERR("BUG! SPQ ring full!\n");
-               spin_unlock(&bp->spq_lock);
+               spin_unlock_bh(&bp->spq_lock);
                bnx2x_panic();
                return -EBUSY;
        }
@@ -1553,18 +1911,18 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
                bp->spq_prod_idx++;
        }
 
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(port),
+       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
               bp->spq_prod_idx);
 
-       spin_unlock(&bp->spq_lock);
+       spin_unlock_bh(&bp->spq_lock);
        return 0;
 }
 
 /* acquire split MCP access lock register */
 static int bnx2x_lock_alr(struct bnx2x *bp)
 {
-       int rc = 0;
        u32 i, j, val;
+       int rc = 0;
 
        might_sleep();
        i = 100;
@@ -1577,10 +1935,8 @@ static int bnx2x_lock_alr(struct bnx2x *bp)
 
                msleep(5);
        }
-
        if (!(val & (1L << 31))) {
                BNX2X_ERR("Cannot acquire nvram interface\n");
-
                rc = -EBUSY;
        }
 
@@ -1631,8 +1987,9 @@ static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
 
 static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 {
-       int port = bp->port;
-       u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_PORT_BASE * port) * 8;
+       int port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
+       u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_FUNC_BASE * func) * 8;
        u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
                              MISC_REG_AEU_MASK_ATTN_FUNC_0;
        u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
@@ -1716,14 +2073,14 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 
 static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int reg_offset;
        u32 val;
 
-       if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) {
+       reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
+                            MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
 
-               reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
-                                    MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
+       if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) {
 
                val = REG_RD(bp, reg_offset);
                val &= ~AEU_INPUTS_ATTN_BITS_SPIO5;
@@ -1731,7 +2088,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
 
                BNX2X_ERR("SPIO5 hw attention\n");
 
-               switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+               switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
                case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
                        /* Fan failure attention */
 
@@ -1762,6 +2119,17 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
                        break;
                }
        }
+
+       if (attn & HW_INTERRUT_ASSERT_SET_0) {
+
+               val = REG_RD(bp, reg_offset);
+               val &= ~(attn & HW_INTERRUT_ASSERT_SET_0);
+               REG_WR(bp, reg_offset, val);
+
+               BNX2X_ERR("FATAL HW block attention set0 0x%x\n",
+                         (attn & HW_INTERRUT_ASSERT_SET_0));
+               bnx2x_panic();
+       }
 }
 
 static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
@@ -1776,6 +2144,23 @@ static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
                if (val & 0x2)
                        BNX2X_ERR("FATAL error from DORQ\n");
        }
+
+       if (attn & HW_INTERRUT_ASSERT_SET_1) {
+
+               int port = BP_PORT(bp);
+               int reg_offset;
+
+               reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1 :
+                                    MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1);
+
+               val = REG_RD(bp, reg_offset);
+               val &= ~(attn & HW_INTERRUT_ASSERT_SET_1);
+               REG_WR(bp, reg_offset, val);
+
+               BNX2X_ERR("FATAL HW block attention set1 0x%x\n",
+                         (attn & HW_INTERRUT_ASSERT_SET_1));
+               bnx2x_panic();
+       }
 }
 
 static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
@@ -1799,13 +2184,41 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
                if (val & 0x18000)
                        BNX2X_ERR("FATAL error from PXP\n");
        }
+
+       if (attn & HW_INTERRUT_ASSERT_SET_2) {
+
+               int port = BP_PORT(bp);
+               int reg_offset;
+
+               reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_2 :
+                                    MISC_REG_AEU_ENABLE1_FUNC_0_OUT_2);
+
+               val = REG_RD(bp, reg_offset);
+               val &= ~(attn & HW_INTERRUT_ASSERT_SET_2);
+               REG_WR(bp, reg_offset, val);
+
+               BNX2X_ERR("FATAL HW block attention set2 0x%x\n",
+                         (attn & HW_INTERRUT_ASSERT_SET_2));
+               bnx2x_panic();
+       }
 }
 
 static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
 {
+       u32 val;
+
        if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) {
 
-               if (attn & BNX2X_MC_ASSERT_BITS) {
+               if (attn & BNX2X_PMF_LINK_ASSERT) {
+                       int func = BP_FUNC(bp);
+
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+                       bnx2x__link_status_update(bp);
+                       if (SHMEM_RD(bp, func_mb[func].drv_status) &
+                                                       DRV_STATUS_PMF)
+                               bnx2x_pmf_update(bp);
+
+               } else if (attn & BNX2X_MC_ASSERT_BITS) {
 
                        BNX2X_ERR("MC assert!\n");
                        REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
@@ -1818,16 +2231,25 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
 
                        BNX2X_ERR("MCP assert!\n");
                        REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_11, 0);
-                       bnx2x_mc_assert(bp);
+                       bnx2x_fw_dump(bp);
 
                } else
                        BNX2X_ERR("Unknown HW assert! (attn 0x%x)\n", attn);
        }
 
        if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
-
+               BNX2X_ERR("LATCHED attention 0x%08x (masked)\n", attn);
+               if (attn & BNX2X_GRC_TIMEOUT) {
+                       val = CHIP_IS_E1H(bp) ?
+                               REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN) : 0;
+                       BNX2X_ERR("GRC time-out 0x%08x\n", val);
+               }
+               if (attn & BNX2X_GRC_RSV) {
+                       val = CHIP_IS_E1H(bp) ?
+                               REG_RD(bp, MISC_REG_GRC_RSV_ATTN) : 0;
+                       BNX2X_ERR("GRC reserved 0x%08x\n", val);
+               }
                REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
-               BNX2X_ERR("LATCHED attention 0x%x (masked)\n", attn);
        }
 }
 
@@ -1835,7 +2257,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
 {
        struct attn_route attn;
        struct attn_route group_mask;
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int index;
        u32 reg_addr;
        u32 val;
@@ -1848,14 +2270,16 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
        attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
        attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
        attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
-       DP(NETIF_MSG_HW, "attn %llx\n", (unsigned long long)attn.sig[0]);
+       DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x\n",
+          attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3]);
 
        for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
                if (deasserted & (1 << index)) {
                        group_mask = bp->attn_group[index];
 
-                       DP(NETIF_MSG_HW, "group[%d]: %llx\n", index,
-                          (unsigned long long)group_mask.sig[0]);
+                       DP(NETIF_MSG_HW, "group[%d]: %08x %08x %08x %08x\n",
+                          index, group_mask.sig[0], group_mask.sig[1],
+                          group_mask.sig[2], group_mask.sig[3]);
 
                        bnx2x_attn_int_deasserted3(bp,
                                        attn.sig[3] & group_mask.sig[3]);
@@ -1866,22 +2290,6 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
                        bnx2x_attn_int_deasserted0(bp,
                                        attn.sig[0] & group_mask.sig[0]);
 
-                       if ((attn.sig[0] & group_mask.sig[0] &
-                                               HW_INTERRUT_ASSERT_SET_0) ||
-                           (attn.sig[1] & group_mask.sig[1] &
-                                               HW_INTERRUT_ASSERT_SET_1) ||
-                           (attn.sig[2] & group_mask.sig[2] &
-                                               HW_INTERRUT_ASSERT_SET_2))
-                               BNX2X_ERR("FATAL HW block attention"
-                                         "  set0 0x%x  set1 0x%x"
-                                         "  set2 0x%x\n",
-                                         (attn.sig[0] & group_mask.sig[0] &
-                                          HW_INTERRUT_ASSERT_SET_0),
-                                         (attn.sig[1] & group_mask.sig[1] &
-                                          HW_INTERRUT_ASSERT_SET_1),
-                                         (attn.sig[2] & group_mask.sig[2] &
-                                          HW_INTERRUT_ASSERT_SET_2));
-
                        if ((attn.sig[0] & group_mask.sig[0] &
                                                HW_PRTY_ASSERT_SET_0) ||
                            (attn.sig[1] & group_mask.sig[1] &
@@ -1894,17 +2302,17 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
 
        bnx2x_unlock_alr(bp);
 
-       reg_addr = (IGU_ADDR_ATTN_BITS_CLR + IGU_PORT_BASE * port) * 8;
+       reg_addr = (IGU_ADDR_ATTN_BITS_CLR + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
 
        val = ~deasserted;
-/*      DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
+/*     DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
           val, BAR_IGU_INTMEM + reg_addr); */
        REG_WR(bp, BAR_IGU_INTMEM + reg_addr, val);
 
        if (bp->aeu_mask & (deasserted & 0xff))
-               BNX2X_ERR("IGU BUG\n");
+               BNX2X_ERR("IGU BUG!\n");
        if (~bp->attn_state & deasserted)
-               BNX2X_ERR("IGU BUG\n");
+               BNX2X_ERR("IGU BUG!\n");
 
        reg_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
                          MISC_REG_AEU_MASK_ATTN_FUNC_0;
@@ -1936,7 +2344,7 @@ static void bnx2x_attn_int(struct bnx2x *bp)
           attn_bits, attn_ack, asserted, deasserted);
 
        if (~(attn_bits ^ attn_ack) & (attn_bits ^ attn_state))
-               BNX2X_ERR("bad attention state\n");
+               BNX2X_ERR("BAD attention state\n");
 
        /* handle bits that were raised */
        if (asserted)
@@ -1951,6 +2359,7 @@ static void bnx2x_sp_task(struct work_struct *work)
        struct bnx2x *bp = container_of(work, struct bnx2x, sp_task);
        u16 status;
 
+
        /* Return here if interrupt is disabled */
        if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
                DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
@@ -1958,19 +2367,15 @@ static void bnx2x_sp_task(struct work_struct *work)
        }
 
        status = bnx2x_update_dsb_idx(bp);
-       if (status == 0)
-               BNX2X_ERR("spurious slowpath interrupt!\n");
+/*     if (status == 0)                                     */
+/*             BNX2X_ERR("spurious slowpath interrupt!\n"); */
 
-       DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status);
+       DP(BNX2X_MSG_SP, "got a slowpath interrupt (updated %x)\n", status);
 
        /* HW attentions */
        if (status & 0x1)
                bnx2x_attn_int(bp);
 
-       /* CStorm events: query_stats, port delete ramrod */
-       if (status & 0x2)
-               bp->stat_pending = 0;
-
        bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, bp->def_att_idx,
                     IGU_INT_NOP, 1);
        bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx),
@@ -2109,13 +2514,13 @@ static inline long bnx2x_hilo(u32 *hiref)
 static void bnx2x_init_mac_stats(struct bnx2x *bp)
 {
        struct dmae_command *dmae;
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int loader_idx = port * 8;
        u32 opcode;
        u32 mac_addr;
 
        bp->executer_idx = 0;
-       if (bp->fw_mb) {
+       if (bp->func_stx) {
                /* MCP */
                opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
                          DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
@@ -2135,7 +2540,7 @@ static void bnx2x_init_mac_stats(struct bnx2x *bp)
                                           sizeof(u32));
                dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, eth_stats) +
                                           sizeof(u32));
-               dmae->dst_addr_lo = bp->fw_mb >> 2;
+               dmae->dst_addr_lo = bp->func_stx >> 2;
                dmae->dst_addr_hi = 0;
                dmae->len = (offsetof(struct bnx2x_eth_stats, mac_stx_end) -
                             sizeof(u32)) >> 2;
@@ -2280,7 +2685,7 @@ static void bnx2x_init_mac_stats(struct bnx2x *bp)
 
 static void bnx2x_init_stats(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
 
        bp->stats_state = STATS_STATE_DISABLE;
        bp->executer_idx = 0;
@@ -2641,8 +3046,6 @@ static void bnx2x_update_net_stats(struct bnx2x *bp)
 
 static void bnx2x_update_stats(struct bnx2x *bp)
 {
-       int i;
-
        if (!bnx2x_update_storm_stats(bp)) {
 
                if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
@@ -2662,6 +3065,7 @@ static void bnx2x_update_stats(struct bnx2x *bp)
        if (bp->msglevel & NETIF_MSG_TIMER) {
                struct bnx2x_eth_stats *estats = bnx2x_sp(bp, eth_stats);
                struct net_device_stats *nstats = &bp->dev->stats;
+               int i;
 
                printk(KERN_DEBUG "%s:\n", bp->dev->name);
                printk(KERN_DEBUG "  tx avail (%4x)  tx hc idx (%x)"
@@ -2707,7 +3111,7 @@ static void bnx2x_update_stats(struct bnx2x *bp)
        /* loader */
        if (bp->executer_idx) {
                struct dmae_command *dmae = &bp->dmae;
-               int port = bp->port;
+               int port = BP_PORT(bp);
                int loader_idx = port * 8;
 
                memset(dmae, 0, sizeof(struct dmae_command));
@@ -2766,8 +3170,8 @@ static void bnx2x_timer(unsigned long data)
                rc = bnx2x_rx_int(fp, 1000);
        }
 
-       if (!nomcp) {
-               int port = bp->port;
+       if (!BP_NOMCP(bp)) {
+               int func = BP_FUNC(bp);
                u32 drv_pulse;
                u32 mcp_pulse;
 
@@ -2775,9 +3179,9 @@ static void bnx2x_timer(unsigned long data)
                bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
                /* TBD - add SYSTEM_TIME */
                drv_pulse = bp->fw_drv_pulse_wr_seq;
-               SHMEM_WR(bp, func_mb[port].drv_pulse_mb, drv_pulse);
+               SHMEM_WR(bp, func_mb[func].drv_pulse_mb, drv_pulse);
 
-               mcp_pulse = (SHMEM_RD(bp, func_mb[port].mcp_pulse_mb) &
+               mcp_pulse = (SHMEM_RD(bp, func_mb[func].mcp_pulse_mb) &
                             MCP_PULSE_SEQ_MASK);
                /* The delta between driver pulse and mcp response
                 * should be 1 (before mcp response) or 0 (after mcp response)
@@ -2807,58 +3211,89 @@ timer_restart:
  * nic init service functions
  */
 
-static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
-                         dma_addr_t mapping, int id)
+static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id)
 {
-       int port = bp->port;
-       u64 section;
+       int port = BP_PORT(bp);
+
+       bnx2x_init_fill(bp, BAR_USTRORM_INTMEM +
+                       USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
+                       sizeof(struct ustorm_def_status_block)/4);
+       bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM +
+                       CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
+                       sizeof(struct cstorm_def_status_block)/4);
+}
+
+static void bnx2x_init_sb(struct bnx2x *bp, int sb_id,
+                         struct host_status_block *sb, dma_addr_t mapping)
+{
+       int port = BP_PORT(bp);
        int index;
+       u64 section;
 
        /* USTORM */
        section = ((u64)mapping) + offsetof(struct host_status_block,
                                            u_status_block);
-       sb->u_status_block.status_block_id = id;
+       sb->u_status_block.status_block_id = sb_id;
 
        REG_WR(bp, BAR_USTRORM_INTMEM +
-              USTORM_SB_HOST_SB_ADDR_OFFSET(port, id), U64_LO(section));
+              USTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id), U64_LO(section));
        REG_WR(bp, BAR_USTRORM_INTMEM +
-              ((USTORM_SB_HOST_SB_ADDR_OFFSET(port, id)) + 4),
+              ((USTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id)) + 4),
               U64_HI(section));
 
        for (index = 0; index < HC_USTORM_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_USTRORM_INTMEM +
-                        USTORM_SB_HC_DISABLE_OFFSET(port, id, index), 0x1);
+                        USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, index), 1);
 
        /* CSTORM */
        section = ((u64)mapping) + offsetof(struct host_status_block,
                                            c_status_block);
-       sb->c_status_block.status_block_id = id;
+       sb->c_status_block.status_block_id = sb_id;
 
        REG_WR(bp, BAR_CSTRORM_INTMEM +
-              CSTORM_SB_HOST_SB_ADDR_OFFSET(port, id), U64_LO(section));
+              CSTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id), U64_LO(section));
        REG_WR(bp, BAR_CSTRORM_INTMEM +
-              ((CSTORM_SB_HOST_SB_ADDR_OFFSET(port, id)) + 4),
+              ((CSTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id)) + 4),
               U64_HI(section));
 
        for (index = 0; index < HC_CSTORM_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_CSTRORM_INTMEM +
-                        CSTORM_SB_HC_DISABLE_OFFSET(port, id, index), 0x1);
+                        CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, index), 1);
+
+       bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+}
+
+static void bnx2x_zero_def_sb(struct bnx2x *bp)
+{
+       int func = BP_FUNC(bp);
 
-       bnx2x_ack_sb(bp, id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+       bnx2x_init_fill(bp, BAR_USTRORM_INTMEM +
+                       USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+                       sizeof(struct ustorm_def_status_block)/4);
+       bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM +
+                       CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+                       sizeof(struct cstorm_def_status_block)/4);
+       bnx2x_init_fill(bp, BAR_XSTRORM_INTMEM +
+                       XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+                       sizeof(struct xstorm_def_status_block)/4);
+       bnx2x_init_fill(bp, BAR_TSTRORM_INTMEM +
+                       TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+                       sizeof(struct tstorm_def_status_block)/4);
 }
 
 static void bnx2x_init_def_sb(struct bnx2x *bp,
                              struct host_def_status_block *def_sb,
-                             dma_addr_t mapping, int id)
+                             dma_addr_t mapping, int sb_id)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
        int index, val, reg_offset;
        u64 section;
 
        /* ATTN */
        section = ((u64)mapping) + offsetof(struct host_def_status_block,
                                            atten_status_block);
-       def_sb->atten_status_block.status_block_id = id;
+       def_sb->atten_status_block.status_block_id = sb_id;
 
        bp->def_att_idx = 0;
        bp->attn_state = 0;
@@ -2866,7 +3301,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
        reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
                             MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
 
-       for (index = 0; index < 3; index++) {
+       for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
                bp->attn_group[index].sig[0] = REG_RD(bp,
                                                     reg_offset + 0x10*index);
                bp->attn_group[index].sig[1] = REG_RD(bp,
@@ -2889,116 +3324,123 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
        reg_offset = (port ? HC_REG_ATTN_NUM_P1 : HC_REG_ATTN_NUM_P0);
 
        val = REG_RD(bp, reg_offset);
-       val |= id;
+       val |= sb_id;
        REG_WR(bp, reg_offset, val);
 
        /* USTORM */
        section = ((u64)mapping) + offsetof(struct host_def_status_block,
                                            u_def_status_block);
-       def_sb->u_def_status_block.status_block_id = id;
+       def_sb->u_def_status_block.status_block_id = sb_id;
 
        bp->def_u_idx = 0;
 
        REG_WR(bp, BAR_USTRORM_INTMEM +
-              USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+              USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_USTRORM_INTMEM +
-              ((USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+              ((USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(port),
+       REG_WR8(bp, BAR_USTRORM_INTMEM +  DEF_USB_FUNC_OFF +
+               USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+       REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(func),
               BNX2X_BTR);
 
        for (index = 0; index < HC_USTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_USTRORM_INTMEM +
-                        USTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
+                        USTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
 
        /* CSTORM */
        section = ((u64)mapping) + offsetof(struct host_def_status_block,
                                            c_def_status_block);
-       def_sb->c_def_status_block.status_block_id = id;
+       def_sb->c_def_status_block.status_block_id = sb_id;
 
        bp->def_c_idx = 0;
 
        REG_WR(bp, BAR_CSTRORM_INTMEM +
-              CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+              CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_CSTRORM_INTMEM +
-              ((CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+              ((CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(port),
+       REG_WR8(bp, BAR_CSTRORM_INTMEM +  DEF_CSB_FUNC_OFF +
+               CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(func),
               BNX2X_BTR);
 
        for (index = 0; index < HC_CSTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_CSTRORM_INTMEM +
-                        CSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
+                        CSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
 
        /* TSTORM */
        section = ((u64)mapping) + offsetof(struct host_def_status_block,
                                            t_def_status_block);
-       def_sb->t_def_status_block.status_block_id = id;
+       def_sb->t_def_status_block.status_block_id = sb_id;
 
        bp->def_t_idx = 0;
 
        REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+              TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_TSTRORM_INTMEM +
-              ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+              ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(port),
+       REG_WR8(bp, BAR_TSTRORM_INTMEM +  DEF_TSB_FUNC_OFF +
+               TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(func),
               BNX2X_BTR);
 
        for (index = 0; index < HC_TSTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_TSTRORM_INTMEM +
-                        TSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
+                        TSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
 
        /* XSTORM */
        section = ((u64)mapping) + offsetof(struct host_def_status_block,
                                            x_def_status_block);
-       def_sb->x_def_status_block.status_block_id = id;
+       def_sb->x_def_status_block.status_block_id = sb_id;
 
        bp->def_x_idx = 0;
 
        REG_WR(bp, BAR_XSTRORM_INTMEM +
-              XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+              XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_XSTRORM_INTMEM +
-              ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+              ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port),
+       REG_WR8(bp, BAR_XSTRORM_INTMEM +  DEF_XSB_FUNC_OFF +
+               XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(func),
               BNX2X_BTR);
 
        for (index = 0; index < HC_XSTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_XSTRORM_INTMEM +
-                        XSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
-
-       bp->stat_pending = 0;
+                        XSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
 
-       bnx2x_ack_sb(bp, id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+       bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
 }
 
 static void bnx2x_update_coalesce(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int i;
 
        for_each_queue(bp, i) {
+               int sb_id = bp->fp[i].sb_id;
 
                /* HC_INDEX_U_ETH_RX_CQ_CONS */
                REG_WR8(bp, BAR_USTRORM_INTMEM +
-                       USTORM_SB_HC_TIMEOUT_OFFSET(port, i,
+                       USTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
                                                   HC_INDEX_U_ETH_RX_CQ_CONS),
-                       bp->rx_ticks_int/12);
+                       bp->rx_ticks/12);
                REG_WR16(bp, BAR_USTRORM_INTMEM +
-                        USTORM_SB_HC_DISABLE_OFFSET(port, i,
+                        USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
                                                   HC_INDEX_U_ETH_RX_CQ_CONS),
-                        bp->rx_ticks_int ? 0 : 1);
+                        bp->rx_ticks ? 0 : 1);
 
                /* HC_INDEX_C_ETH_TX_CQ_CONS */
                REG_WR8(bp, BAR_CSTRORM_INTMEM +
-                       CSTORM_SB_HC_TIMEOUT_OFFSET(port, i,
+                       CSTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
                                                   HC_INDEX_C_ETH_TX_CQ_CONS),
-                       bp->tx_ticks_int/12);
+                       bp->tx_ticks/12);
                REG_WR16(bp, BAR_CSTRORM_INTMEM +
-                        CSTORM_SB_HC_DISABLE_OFFSET(port, i,
+                        CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
                                                   HC_INDEX_C_ETH_TX_CQ_CONS),
-                        bp->tx_ticks_int ? 0 : 1);
+                        bp->tx_ticks ? 0 : 1);
        }
 }
 
@@ -3006,7 +3448,6 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
 {
        u16 ring_prod;
        int i, j;
-       int port = bp->port;
 
        bp->rx_buf_use_size = bp->dev->mtu;
 
@@ -3025,13 +3466,13 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                        rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
                        rx_bd->addr_hi =
                                cpu_to_le32(U64_HI(fp->rx_desc_mapping +
-                                          BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
+                                           BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
                        rx_bd->addr_lo =
                                cpu_to_le32(U64_LO(fp->rx_desc_mapping +
-                                          BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
-
+                                           BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
                }
 
+               /* CQ ring */
                for (i = 1; i <= NUM_RCQ_RINGS; i++) {
                        struct eth_rx_cqe_next_page *nextpg;
 
@@ -3039,10 +3480,10 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                                &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
                        nextpg->addr_hi =
                                cpu_to_le32(U64_HI(fp->rx_comp_mapping +
-                                         BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+                                          BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
                        nextpg->addr_lo =
                                cpu_to_le32(U64_LO(fp->rx_comp_mapping +
-                                         BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+                                          BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
                }
 
                /* rx completion queue */
@@ -3064,15 +3505,16 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                /* Warning! this will generate an interrupt (to the TSTORM) */
                /* must only be done when chip is initialized */
                REG_WR(bp, BAR_TSTRORM_INTMEM +
-                      TSTORM_RCQ_PROD_OFFSET(port, j), ring_prod);
+                      TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)),
+                       ring_prod);
                if (j != 0)
                        continue;
 
                REG_WR(bp, BAR_USTRORM_INTMEM +
-                      USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(port),
+                      USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(BP_PORT(bp)),
                       U64_LO(fp->rx_comp_mapping));
                REG_WR(bp, BAR_USTRORM_INTMEM +
-                      USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(port) + 4,
+                      USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(BP_PORT(bp)) + 4,
                       U64_HI(fp->rx_comp_mapping));
        }
 }
@@ -3090,10 +3532,10 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp)
 
                        tx_bd->addr_hi =
                                cpu_to_le32(U64_HI(fp->tx_desc_mapping +
-                                          BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
+                                           BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
                        tx_bd->addr_lo =
                                cpu_to_le32(U64_LO(fp->tx_desc_mapping +
-                                          BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
+                                           BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
                }
 
                fp->tx_pkt_prod = 0;
@@ -3107,7 +3549,7 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp)
 
 static void bnx2x_init_sp_ring(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int func = BP_FUNC(bp);
 
        spin_lock_init(&bp->spq_lock);
 
@@ -3117,12 +3559,13 @@ static void bnx2x_init_sp_ring(struct bnx2x *bp)
        bp->spq_prod_bd = bp->spq;
        bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT;
 
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PAGE_BASE_OFFSET(port),
+       REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func),
               U64_LO(bp->spq_mapping));
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PAGE_BASE_OFFSET(port) + 4,
+       REG_WR(bp,
+              XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func) + 4,
               U64_HI(bp->spq_mapping));
 
-       REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(port),
+       REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(func),
               bp->spq_prod_idx);
 }
 
@@ -3133,6 +3576,7 @@ static void bnx2x_init_context(struct bnx2x *bp)
        for_each_queue(bp, i) {
                struct eth_context *context = bnx2x_sp(bp, context[i].eth);
                struct bnx2x_fastpath *fp = &bp->fp[i];
+               u8 sb_id = FP_SB_ID(fp);
 
                context->xstorm_st_context.tx_bd_page_base_hi =
                                                U64_HI(fp->tx_desc_mapping);
@@ -3142,26 +3586,25 @@ static void bnx2x_init_context(struct bnx2x *bp)
                                                U64_HI(fp->tx_prods_mapping);
                context->xstorm_st_context.db_data_addr_lo =
                                                U64_LO(fp->tx_prods_mapping);
-
-               context->ustorm_st_context.rx_bd_page_base_hi =
+               context->xstorm_st_context.statistics_data = (BP_CL_ID(bp) |
+                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+
+               context->ustorm_st_context.common.sb_index_numbers =
+                                               BNX2X_RX_SB_INDEX_NUM;
+               context->ustorm_st_context.common.clientId = FP_CL_ID(fp);
+               context->ustorm_st_context.common.status_block_id = sb_id;
+               context->ustorm_st_context.common.flags =
+                       USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT;
+               context->ustorm_st_context.common.mc_alignment_size = 64;
+               context->ustorm_st_context.common.bd_buff_size =
+                                               bp->rx_buf_use_size;
+               context->ustorm_st_context.common.bd_page_base_hi =
                                                U64_HI(fp->rx_desc_mapping);
-               context->ustorm_st_context.rx_bd_page_base_lo =
+               context->ustorm_st_context.common.bd_page_base_lo =
                                                U64_LO(fp->rx_desc_mapping);
-               context->ustorm_st_context.status_block_id = i;
-               context->ustorm_st_context.sb_index_number =
-                                               HC_INDEX_U_ETH_RX_CQ_CONS;
-               context->ustorm_st_context.rcq_base_address_hi =
-                                               U64_HI(fp->rx_comp_mapping);
-               context->ustorm_st_context.rcq_base_address_lo =
-                                               U64_LO(fp->rx_comp_mapping);
-               context->ustorm_st_context.flags =
-                               USTORM_ETH_ST_CONTEXT_ENABLE_MC_ALIGNMENT;
-               context->ustorm_st_context.mc_alignment_size = 64;
-               context->ustorm_st_context.num_rss = bp->num_queues;
-
                context->cstorm_st_context.sb_index_number =
                                                HC_INDEX_C_ETH_TX_CQ_CONS;
-               context->cstorm_st_context.status_block_id = i;
+               context->cstorm_st_context.status_block_id = sb_id;
 
                context->xstorm_ag_context.cdu_reserved =
                        CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
@@ -3176,14 +3619,16 @@ static void bnx2x_init_context(struct bnx2x *bp)
 
 static void bnx2x_init_ind_table(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int i;
 
        if (!is_multi(bp))
                return;
 
+       DP(NETIF_MSG_IFUP, "Initializing indirection table\n");
        for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
-               REG_WR8(bp, TSTORM_INDIRECTION_TABLE_OFFSET(port) + i,
+               REG_WR8(bp, BAR_TSTRORM_INTMEM +
+                       TSTORM_INDIRECTION_TABLE_OFFSET(port) + i,
                        i % bp->num_queues);
 
        REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
@@ -3191,77 +3636,74 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
 
 static void bnx2x_set_client_config(struct bnx2x *bp)
 {
-#ifdef BCM_VLAN
-       int mode = bp->rx_mode;
-#endif
-       int i, port = bp->port;
        struct tstorm_eth_client_config tstorm_client = {0};
+       int port = BP_PORT(bp);
+       int i;
 
-       tstorm_client.mtu = bp->dev->mtu;
+       tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD;
        tstorm_client.statistics_counter_id = 0;
        tstorm_client.config_flags =
                                TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
 #ifdef BCM_VLAN
-       if (mode && bp->vlgrp) {
+       if (bp->rx_mode && bp->vlgrp) {
                tstorm_client.config_flags |=
                                TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
                DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
        }
 #endif
-       if (mode != BNX2X_RX_MODE_PROMISC)
-               tstorm_client.drop_flags =
-                               TSTORM_ETH_CLIENT_CONFIG_DROP_MAC_ERR;
 
        for_each_queue(bp, i) {
                REG_WR(bp, BAR_TSTRORM_INTMEM +
-                      TSTORM_CLIENT_CONFIG_OFFSET(port, i),
+                      TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id),
                       ((u32 *)&tstorm_client)[0]);
                REG_WR(bp, BAR_TSTRORM_INTMEM +
-                      TSTORM_CLIENT_CONFIG_OFFSET(port, i) + 4,
+                      TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id) + 4,
                       ((u32 *)&tstorm_client)[1]);
        }
 
-/*     DP(NETIF_MSG_IFUP, "tstorm_client: 0x%08x 0x%08x\n",
-          ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]); */
+       DP(BNX2X_MSG_OFF, "tstorm_client: 0x%08x 0x%08x\n",
+          ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]);
 }
 
 static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 {
-       int mode = bp->rx_mode;
-       int port = bp->port;
        struct tstorm_eth_mac_filter_config tstorm_mac_filter = {0};
+       int mode = bp->rx_mode;
+       int mask = (1 << BP_L_ID(bp));
+       int func = BP_FUNC(bp);
        int i;
 
        DP(NETIF_MSG_RX_STATUS, "rx mode is %d\n", mode);
 
        switch (mode) {
        case BNX2X_RX_MODE_NONE: /* no Rx */
-               tstorm_mac_filter.ucast_drop_all = 1;
-               tstorm_mac_filter.mcast_drop_all = 1;
-               tstorm_mac_filter.bcast_drop_all = 1;
+               tstorm_mac_filter.ucast_drop_all = mask;
+               tstorm_mac_filter.mcast_drop_all = mask;
+               tstorm_mac_filter.bcast_drop_all = mask;
                break;
        case BNX2X_RX_MODE_NORMAL:
-               tstorm_mac_filter.bcast_accept_all = 1;
+               tstorm_mac_filter.bcast_accept_all = mask;
                break;
        case BNX2X_RX_MODE_ALLMULTI:
-               tstorm_mac_filter.mcast_accept_all = 1;
-               tstorm_mac_filter.bcast_accept_all = 1;
+               tstorm_mac_filter.mcast_accept_all = mask;
+               tstorm_mac_filter.bcast_accept_all = mask;
                break;
        case BNX2X_RX_MODE_PROMISC:
-               tstorm_mac_filter.ucast_accept_all = 1;
-               tstorm_mac_filter.mcast_accept_all = 1;
-               tstorm_mac_filter.bcast_accept_all = 1;
+               tstorm_mac_filter.ucast_accept_all = mask;
+               tstorm_mac_filter.mcast_accept_all = mask;
+               tstorm_mac_filter.bcast_accept_all = mask;
                break;
        default:
-               BNX2X_ERR("bad rx mode (%d)\n", mode);
+               BNX2X_ERR("BAD rx mode (%d)\n", mode);
+               break;
        }
 
        for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) {
                REG_WR(bp, BAR_TSTRORM_INTMEM +
-                      TSTORM_MAC_FILTER_CONFIG_OFFSET(port) + i * 4,
+                      TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4,
                       ((u32 *)&tstorm_mac_filter)[i]);
 
-/*             DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
+/*             DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
                   ((u32 *)&tstorm_mac_filter)[i]); */
        }
 
@@ -3271,26 +3713,30 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 
 static void bnx2x_init_internal(struct bnx2x *bp)
 {
-       int port = bp->port;
        struct tstorm_eth_function_common_config tstorm_config = {0};
        struct stats_indication_flags stats_flags = {0};
+       int port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
+       int i;
 
        if (is_multi(bp)) {
                tstorm_config.config_flags = MULTI_FLAGS;
                tstorm_config.rss_result_mask = MULTI_MASK;
        }
 
+       tstorm_config.leading_client_id = BP_L_ID(bp);
+
        REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(port),
+              TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(func),
               (*(u32 *)&tstorm_config));
 
-/*      DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n",
+/*     DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n",
           (*(u32 *)&tstorm_config)); */
 
        bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */
        bnx2x_set_storm_rx_mode(bp);
 
-       stats_flags.collect_eth = cpu_to_le32(1);
+       stats_flags.collect_eth = 1;
 
        REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(port),
               ((u32 *)&stats_flags)[0]);
@@ -3307,8 +3753,28 @@ static void bnx2x_init_internal(struct bnx2x *bp)
        REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(port) + 4,
               ((u32 *)&stats_flags)[1]);
 
-/*      DP(NETIF_MSG_IFUP, "stats_flags: 0x%08x 0x%08x\n",
+/*     DP(NETIF_MSG_IFUP, "stats_flags: 0x%08x 0x%08x\n",
           ((u32 *)&stats_flags)[0], ((u32 *)&stats_flags)[1]); */
+
+       if (CHIP_IS_E1H(bp)) {
+               REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
+                       IS_E1HMF(bp));
+               REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
+                       IS_E1HMF(bp));
+               REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
+                       IS_E1HMF(bp));
+               REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
+                       IS_E1HMF(bp));
+
+               REG_WR16(bp, BAR_XSTRORM_INTMEM +
+                        XSTORM_E1HOV_OFFSET(func), bp->e1hov);
+       }
+
+       /* Zero this manualy as its initialization is
+          currently missing in the initTool */
+       for (i = 0; i < USTORM_AGG_DATA_SIZE >> 2; i++)
+               REG_WR(bp, BAR_USTRORM_INTMEM +
+                      USTORM_AGG_DATA_OFFSET + 4*i, 0);
 }
 
 static void bnx2x_nic_init(struct bnx2x *bp)
@@ -3318,15 +3784,20 @@ static void bnx2x_nic_init(struct bnx2x *bp)
        for_each_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
 
+               fp->bp = bp;
                fp->state = BNX2X_FP_STATE_CLOSED;
-               DP(NETIF_MSG_IFUP, "bnx2x_init_sb(%p,%p,%d);\n",
-                  bp, fp->status_blk, i);
                fp->index = i;
-               bnx2x_init_sb(bp, fp->status_blk, fp->status_blk_mapping, i);
+               fp->cl_id = BP_L_ID(bp) + i;
+               fp->sb_id = fp->cl_id;
+               DP(NETIF_MSG_IFUP,
+                  "bnx2x_init_sb(%p,%p) index %d  cl_id %d  sb %d\n",
+                  bp, fp->status_blk, i, FP_CL_ID(fp), FP_SB_ID(fp));
+               bnx2x_init_sb(bp, FP_SB_ID(fp), fp->status_blk,
+                             fp->status_blk_mapping);
        }
 
        bnx2x_init_def_sb(bp, bp->def_status_blk,
-                         bp->def_status_blk_mapping, 0x10);
+                         bp->def_status_blk_mapping, DEF_SB_ID);
        bnx2x_update_coalesce(bp);
        bnx2x_init_rx_rings(bp);
        bnx2x_init_tx_ring(bp);
@@ -3336,7 +3807,6 @@ static void bnx2x_nic_init(struct bnx2x *bp)
        bnx2x_init_stats(bp);
        bnx2x_init_ind_table(bp);
        bnx2x_int_enable(bp);
-
 }
 
 /* end of nic init */
@@ -3374,7 +3844,7 @@ gunzip_nomem2:
 
 gunzip_nomem1:
        printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for"
-              " uncompression\n", bp->dev->name);
+              " un-compression\n", bp->dev->name);
        return -ENOMEM;
 }
 
@@ -3402,7 +3872,7 @@ static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len)
 
        n = 10;
 
-#define FNAME                          0x8
+#define FNAME                          0x8
 
        if (zbuf[3] & FNAME)
                while ((zbuf[n++] != 0) && (n < len));
@@ -3439,41 +3909,25 @@ static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len)
 /* nic load/unload */
 
 /*
- * general service functions
+ * General service functions
  */
 
 /* send a NIG loopback debug packet */
 static void bnx2x_lb_pckt(struct bnx2x *bp)
 {
-#ifdef USE_DMAE
        u32 wb_write[3];
-#endif
 
        /* Ethernet source and destination addresses */
-#ifdef USE_DMAE
        wb_write[0] = 0x55555555;
        wb_write[1] = 0x55555555;
-       wb_write[2] = 0x20;             /* SOP */
+       wb_write[2] = 0x20;             /* SOP */
        REG_WR_DMAE(bp, NIG_REG_DEBUG_PACKET_LB, wb_write, 3);
-#else
-       REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB, 0x55555555);
-       REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 4, 0x55555555);
-       /* SOP */
-       REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 8, 0x20);
-#endif
 
        /* NON-IP protocol */
-#ifdef USE_DMAE
        wb_write[0] = 0x09000000;
        wb_write[1] = 0x55555555;
-       wb_write[2] = 0x10;             /* EOP, eop_bvalid = 0 */
+       wb_write[2] = 0x10;             /* EOP, eop_bvalid = 0 */
        REG_WR_DMAE(bp, NIG_REG_DEBUG_PACKET_LB, wb_write, 3);
-#else
-       REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB, 0x09000000);
-       REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 4, 0x55555555);
-       /* EOP, eop_bvalid = 0 */
-       REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 8, 0x10);
-#endif
 }
 
 /* some of the internal memories
@@ -3511,13 +3965,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        /* Wait until NIG register shows 1 packet of size 0x10 */
        count = 1000 * factor;
        while (count) {
-#ifdef BNX2X_DMAE_RD
+
                bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
                val = *bnx2x_sp(bp, wb_data[0]);
-#else
-               val = REG_RD(bp, NIG_REG_STAT2_BRB_OCTET);
-               REG_RD(bp, NIG_REG_STAT2_BRB_OCTET + 4);
-#endif
                if (val == 0x10)
                        break;
 
@@ -3533,7 +3983,6 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        count = 1000 * factor;
        while (count) {
                val = REG_RD(bp, PRS_REG_NUM_OF_PACKETS);
-
                if (val == 1)
                        break;
 
@@ -3546,9 +3995,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        }
 
        /* Reset and init BRB, PRS */
-       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x3);
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x03);
        msleep(50);
-       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x3);
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
        msleep(50);
        bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
        bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
@@ -3572,13 +4021,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
           packets of size 11*0x10 = 0xb0 */
        count = 1000 * factor;
        while (count) {
-#ifdef BNX2X_DMAE_RD
+
                bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
                val = *bnx2x_sp(bp, wb_data[0]);
-#else
-               val = REG_RD(bp, NIG_REG_STAT2_BRB_OCTET);
-               REG_RD(bp, NIG_REG_STAT2_BRB_OCTET + 4);
-#endif
                if (val == 0xb0)
                        break;
 
@@ -3648,85 +4093,75 @@ static void enable_blocks_attention(struct bnx2x *bp)
        REG_WR(bp, XSDM_REG_XSDM_INT_MASK_0, 0);
        REG_WR(bp, XSDM_REG_XSDM_INT_MASK_1, 0);
        REG_WR(bp, XCM_REG_XCM_INT_MASK, 0);
-/*      REG_WR(bp, XSEM_REG_XSEM_INT_MASK_0, 0); */
-/*      REG_WR(bp, XSEM_REG_XSEM_INT_MASK_1, 0); */
+/*     REG_WR(bp, XSEM_REG_XSEM_INT_MASK_0, 0); */
+/*     REG_WR(bp, XSEM_REG_XSEM_INT_MASK_1, 0); */
        REG_WR(bp, USDM_REG_USDM_INT_MASK_0, 0);
        REG_WR(bp, USDM_REG_USDM_INT_MASK_1, 0);
        REG_WR(bp, UCM_REG_UCM_INT_MASK, 0);
-/*      REG_WR(bp, USEM_REG_USEM_INT_MASK_0, 0); */
-/*      REG_WR(bp, USEM_REG_USEM_INT_MASK_1, 0); */
+/*     REG_WR(bp, USEM_REG_USEM_INT_MASK_0, 0); */
+/*     REG_WR(bp, USEM_REG_USEM_INT_MASK_1, 0); */
        REG_WR(bp, GRCBASE_UPB + PB_REG_PB_INT_MASK, 0);
        REG_WR(bp, CSDM_REG_CSDM_INT_MASK_0, 0);
        REG_WR(bp, CSDM_REG_CSDM_INT_MASK_1, 0);
        REG_WR(bp, CCM_REG_CCM_INT_MASK, 0);
-/*      REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
-/*      REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
-       REG_WR(bp, PXP2_REG_PXP2_INT_MASK, 0x480000);
+/*     REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
+/*     REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
+       if (CHIP_REV_IS_FPGA(bp))
+               REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
+       else
+               REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
        REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
        REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
        REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
-/*      REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
-/*      REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */
+/*     REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
+/*     REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */
        REG_WR(bp, CDU_REG_CDU_INT_MASK, 0);
        REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0);
-/*      REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
-       REG_WR(bp, PBF_REG_PBF_INT_MASK, 0X18);         /* bit 3,4 masked */
+/*     REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
+       REG_WR(bp, PBF_REG_PBF_INT_MASK, 0X18);         /* bit 3,4 masked */
 }
 
-static int bnx2x_function_init(struct bnx2x *bp, int mode)
+
+static int bnx2x_init_common(struct bnx2x *bp)
 {
-       int func = bp->port;
-       int port = func ? PORT1 : PORT0;
        u32 val, i;
-#ifdef USE_DMAE
-       u32 wb_write[2];
-#endif
-
-       DP(BNX2X_MSG_MCP, "function is %d  mode is %x\n", func, mode);
-       if ((func != 0) && (func != 1)) {
-               BNX2X_ERR("BAD function number (%d)\n", func);
-               return -ENODEV;
-       }
 
-       bnx2x_gunzip_init(bp);
+       DP(BNX2X_MSG_MCP, "starting common init  func %d\n", BP_FUNC(bp));
 
-       if (mode & 0x1) {       /* init common */
-               DP(BNX2X_MSG_MCP, "starting common init  func %d  mode %x\n",
-                  func, mode);
-               REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
-                      0xffffffff);
-               REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-                      0xfffc);
-               bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END);
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
 
-               REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
-               msleep(30);
-               REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
+       bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END);
+       if (CHIP_IS_E1H(bp))
+               REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp));
 
-               bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END);
-               bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END);
+       REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
+       msleep(30);
+       REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
 
-               bnx2x_init_pxp(bp);
+       bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END);
+       if (CHIP_IS_E1(bp)) {
+               /* enable HW interrupt from PXP on USDM overflow
+                  bit 16 on INT_MASK_0 */
+               REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
+       }
 
-               if (CHIP_REV(bp) == CHIP_REV_Ax) {
-                       /* enable HW interrupt from PXP on USDM
-                          overflow bit 16 on INT_MASK_0 */
-                       REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
-               }
+       bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END);
+       bnx2x_init_pxp(bp);
 
 #ifdef __BIG_ENDIAN
-               REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
-               REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
-               REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
-               REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
-               REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
-               REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1);
-
-/*             REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
-               REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
-               REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
-               REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
-               REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
+       REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
+       REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
+       REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
+       REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
+       REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
+       REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1);
+
+/*     REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
+       REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
+       REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
+       REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
+       REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
 #endif
 
 #ifndef BCM_ISCSI
@@ -3734,92 +4169,105 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
                REG_WR(bp, PRS_REG_NIC_MODE, 1);
 #endif
 
-               REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 5);
+       REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 2);
 #ifdef BCM_ISCSI
-               REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
-               REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5);
-               REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5);
+       REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
+       REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5);
+       REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5);
 #endif
 
-               bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END);
+       if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
+               REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x1);
 
-               /* let the HW do it's magic ... */
-               msleep(100);
-               /* finish PXP init
-                  (can be moved up if we want to use the DMAE) */
-               val = REG_RD(bp, PXP2_REG_RQ_CFG_DONE);
-               if (val != 1) {
-                       BNX2X_ERR("PXP2 CFG failed\n");
-                       return -EBUSY;
-               }
+       /* let the HW do it's magic ... */
+       msleep(100);
+       /* finish PXP init */
+       val = REG_RD(bp, PXP2_REG_RQ_CFG_DONE);
+       if (val != 1) {
+               BNX2X_ERR("PXP2 CFG failed\n");
+               return -EBUSY;
+       }
+       val = REG_RD(bp, PXP2_REG_RD_INIT_DONE);
+       if (val != 1) {
+               BNX2X_ERR("PXP2 RD_INIT failed\n");
+               return -EBUSY;
+       }
 
-               val = REG_RD(bp, PXP2_REG_RD_INIT_DONE);
-               if (val != 1) {
-                       BNX2X_ERR("PXP2 RD_INIT failed\n");
-                       return -EBUSY;
-               }
+       REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
+       REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
 
-               REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
-               REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
+       bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END);
 
-               bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
+       /* clean the DMAE memory */
+       bp->dmae_ready = 1;
+       bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
 
-               bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END);
-               bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END);
-               bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END);
-               bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END);
+       bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END);
+       bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END);
+       bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END);
+       bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END);
 
-#ifdef BNX2X_DMAE_RD
-               bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
-               bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
-               bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
-               bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
-#else
-               REG_RD(bp, XSEM_REG_PASSIVE_BUFFER);
-               REG_RD(bp, XSEM_REG_PASSIVE_BUFFER + 4);
-               REG_RD(bp, XSEM_REG_PASSIVE_BUFFER + 8);
-               REG_RD(bp, CSEM_REG_PASSIVE_BUFFER);
-               REG_RD(bp, CSEM_REG_PASSIVE_BUFFER + 4);
-               REG_RD(bp, CSEM_REG_PASSIVE_BUFFER + 8);
-               REG_RD(bp, TSEM_REG_PASSIVE_BUFFER);
-               REG_RD(bp, TSEM_REG_PASSIVE_BUFFER + 4);
-               REG_RD(bp, TSEM_REG_PASSIVE_BUFFER + 8);
-               REG_RD(bp, USEM_REG_PASSIVE_BUFFER);
-               REG_RD(bp, USEM_REG_PASSIVE_BUFFER + 4);
-               REG_RD(bp, USEM_REG_PASSIVE_BUFFER + 8);
-#endif
-               bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END);
-               /* soft reset pulse */
-               REG_WR(bp, QM_REG_SOFT_RESET, 1);
-               REG_WR(bp, QM_REG_SOFT_RESET, 0);
+       bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
+       bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
+       bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
+       bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
+
+       bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END);
+       /* soft reset pulse */
+       REG_WR(bp, QM_REG_SOFT_RESET, 1);
+       REG_WR(bp, QM_REG_SOFT_RESET, 0);
 
 #ifdef BCM_ISCSI
-               bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END);
+       bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END);
 #endif
-               bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END);
-               REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_BITS);
-               if (CHIP_REV(bp) == CHIP_REV_Ax) {
-                       /* enable hw interrupt from doorbell Q */
-                       REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
-               }
 
-               bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+       bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END);
+       REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT);
+       if (!CHIP_REV_IS_SLOW(bp)) {
+               /* enable hw interrupt from doorbell Q */
+               REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
+       }
 
-               if (CHIP_REV_IS_SLOW(bp)) {
-                       /* fix for emulation and FPGA for no pause */
-                       REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 513);
-                       REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 513);
-                       REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0);
-                       REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0);
-               }
+       bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+       if (CHIP_REV_IS_SLOW(bp)) {
+               /* fix for emulation and FPGA for no pause */
+               REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 513);
+               REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 513);
+               REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0);
+               REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0);
+       }
 
-               bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+       bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+       if (CHIP_IS_E1H(bp))
+               REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
 
-               bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END);
-               bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END);
-               bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END);
-               bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END);
+       bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END);
+       bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END);
+       bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END);
+       bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END);
 
+       if (CHIP_IS_E1H(bp)) {
+               bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0,
+                               STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp,
+                               TSTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+                               0, STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0,
+                               STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp,
+                               CSTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+                               0, STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0,
+                               STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp,
+                               XSTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+                               0, STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0,
+                               STORM_INTMEM_SIZE_E1H/2);
+               bnx2x_init_fill(bp,
+                               USTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+                               0, STORM_INTMEM_SIZE_E1H/2);
+       } else { /* E1 */
                bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0,
                                STORM_INTMEM_SIZE_E1);
                bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0,
@@ -3828,157 +4276,141 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
                                STORM_INTMEM_SIZE_E1);
                bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0,
                                STORM_INTMEM_SIZE_E1);
+       }
 
-               bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END);
-               bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END);
-               bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END);
-               bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END);
-
-               /* sync semi rtc */
-               REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-                      0x80000000);
-               REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
-                      0x80000000);
-
-               bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END);
-               bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END);
-               bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END);
-
-               REG_WR(bp, SRC_REG_SOFT_RST, 1);
-               for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) {
-                       REG_WR(bp, i, 0xc0cac01a);
-                       /* TODO: replace with something meaningful */
-               }
-               /* SRCH COMMON comes here */
-               REG_WR(bp, SRC_REG_SOFT_RST, 0);
-
-               if (sizeof(union cdu_context) != 1024) {
-                       /* we currently assume that a context is 1024 bytes */
-                       printk(KERN_ALERT PFX "please adjust the size of"
-                              " cdu_context(%ld)\n",
-                              (long)sizeof(union cdu_context));
-               }
-               val = (4 << 24) + (0 << 12) + 1024;
-               REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
-               bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END);
-
-               bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END);
-               REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
-
-               bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END);
-               bnx2x_init_block(bp, MISC_AEU_COMMON_START,
-                                MISC_AEU_COMMON_END);
-               /* RXPCS COMMON comes here */
-               /* EMAC0 COMMON comes here */
-               /* EMAC1 COMMON comes here */
-               /* DBU COMMON comes here */
-               /* DBG COMMON comes here */
-               bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END);
+       bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END);
+       bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END);
+       bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END);
+       bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END);
 
-               if (CHIP_REV_IS_SLOW(bp))
-                       msleep(200);
+       /* sync semi rtc */
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+              0x80000000);
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
+              0x80000000);
 
-               /* finish CFC init */
-               val = REG_RD(bp, CFC_REG_LL_INIT_DONE);
-               if (val != 1) {
-                       BNX2X_ERR("CFC LL_INIT failed\n");
-                       return -EBUSY;
-               }
+       bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END);
+       bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END);
+       bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END);
 
-               val = REG_RD(bp, CFC_REG_AC_INIT_DONE);
-               if (val != 1) {
-                       BNX2X_ERR("CFC AC_INIT failed\n");
-                       return -EBUSY;
-               }
+       REG_WR(bp, SRC_REG_SOFT_RST, 1);
+       for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) {
+               REG_WR(bp, i, 0xc0cac01a);
+               /* TODO: replace with something meaningful */
+       }
+       if (CHIP_IS_E1H(bp))
+               bnx2x_init_block(bp, SRCH_COMMON_START, SRCH_COMMON_END);
+       REG_WR(bp, SRC_REG_SOFT_RST, 0);
 
-               val = REG_RD(bp, CFC_REG_CAM_INIT_DONE);
-               if (val != 1) {
-                       BNX2X_ERR("CFC CAM_INIT failed\n");
-                       return -EBUSY;
-               }
+       if (sizeof(union cdu_context) != 1024)
+               /* we currently assume that a context is 1024 bytes */
+               printk(KERN_ALERT PFX "please adjust the size of"
+                      " cdu_context(%ld)\n", (long)sizeof(union cdu_context));
 
-               REG_WR(bp, CFC_REG_DEBUG0, 0);
+       bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END);
+       val = (4 << 24) + (0 << 12) + 1024;
+       REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
+       if (CHIP_IS_E1(bp)) {
+               /* !!! fix pxp client crdit until excel update */
+               REG_WR(bp, CDU_REG_CDU_DEBUG, 0x264);
+               REG_WR(bp, CDU_REG_CDU_DEBUG, 0);
+       }
 
-               /* read NIG statistic
-                  to see if this is our first up since powerup */
-#ifdef BNX2X_DMAE_RD
-               bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
-               val = *bnx2x_sp(bp, wb_data[0]);
-#else
-               val = REG_RD(bp, NIG_REG_STAT2_BRB_OCTET);
-               REG_RD(bp, NIG_REG_STAT2_BRB_OCTET + 4);
-#endif
-               /* do internal memory self test */
-               if ((val == 0) && bnx2x_int_mem_test(bp)) {
-                       BNX2X_ERR("internal mem selftest failed\n");
-                       return -EBUSY;
-               }
+       bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END);
+       REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
 
-               /* clear PXP2 attentions */
-               REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR);
+       bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END);
+       bnx2x_init_block(bp, MISC_AEU_COMMON_START, MISC_AEU_COMMON_END);
 
-               enable_blocks_attention(bp);
-               /* enable_blocks_parity(bp); */
+       /* PXPCS COMMON comes here */
+       /* Reset PCIE errors for debug */
+       REG_WR(bp, 0x2814, 0xffffffff);
+       REG_WR(bp, 0x3820, 0xffffffff);
 
-               switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
-               case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
-                       /* Fan failure is indicated by SPIO 5 */
-                       bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
-                                      MISC_REGISTERS_SPIO_INPUT_HI_Z);
+       /* EMAC0 COMMON comes here */
+       /* EMAC1 COMMON comes here */
+       /* DBU COMMON comes here */
+       /* DBG COMMON comes here */
+
+       bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END);
+       if (CHIP_IS_E1H(bp)) {
+               REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp));
+               REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp));
+       }
+
+       if (CHIP_REV_IS_SLOW(bp))
+               msleep(200);
+
+       /* finish CFC init */
+       val = reg_poll(bp, CFC_REG_LL_INIT_DONE, 1, 100, 10);
+       if (val != 1) {
+               BNX2X_ERR("CFC LL_INIT failed\n");
+               return -EBUSY;
+       }
+       val = reg_poll(bp, CFC_REG_AC_INIT_DONE, 1, 100, 10);
+       if (val != 1) {
+               BNX2X_ERR("CFC AC_INIT failed\n");
+               return -EBUSY;
+       }
+       val = reg_poll(bp, CFC_REG_CAM_INIT_DONE, 1, 100, 10);
+       if (val != 1) {
+               BNX2X_ERR("CFC CAM_INIT failed\n");
+               return -EBUSY;
+       }
+       REG_WR(bp, CFC_REG_DEBUG0, 0);
 
-                       /* set to active low mode */
-                       val = REG_RD(bp, MISC_REG_SPIO_INT);
-                       val |= ((1 << MISC_REGISTERS_SPIO_5) <<
+       /* read NIG statistic
+          to see if this is our first up since powerup */
+       bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
+       val = *bnx2x_sp(bp, wb_data[0]);
+
+       /* do internal memory self test */
+       if ((CHIP_IS_E1(bp)) && (val == 0) && bnx2x_int_mem_test(bp)) {
+               BNX2X_ERR("internal mem self test failed\n");
+               return -EBUSY;
+       }
+
+       switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+       case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
+               /* Fan failure is indicated by SPIO 5 */
+               bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
+                              MISC_REGISTERS_SPIO_INPUT_HI_Z);
+
+               /* set to active low mode */
+               val = REG_RD(bp, MISC_REG_SPIO_INT);
+               val |= ((1 << MISC_REGISTERS_SPIO_5) <<
                                        MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
-                       REG_WR(bp, MISC_REG_SPIO_INT, val);
+               REG_WR(bp, MISC_REG_SPIO_INT, val);
 
-                       /* enable interrupt to signal the IGU */
-                       val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
-                       val |= (1 << MISC_REGISTERS_SPIO_5);
-                       REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
-                       break;
+               /* enable interrupt to signal the IGU */
+               val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+               val |= (1 << MISC_REGISTERS_SPIO_5);
+               REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
+               break;
 
-               default:
-                       break;
-               }
+       default:
+               break;
+       }
 
-       } /* end of common init */
+       /* clear PXP2 attentions */
+       REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
 
-       /* per port init */
+       enable_blocks_attention(bp);
 
-       /* the phys address is shifted right 12 bits and has an added
-          1=valid bit added to the 53rd bit
-          then since this is a wide register(TM)
-          we split it into two 32 bit writes
-        */
-#define RQ_ONCHIP_AT_PORT_SIZE  384
-#define ONCHIP_ADDR1(x)   ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
-#define ONCHIP_ADDR2(x)   ((u32)((1 << 20) | ((u64)x >> 44)))
-#define PXP_ONE_ILT(x)    ((x << 10) | x)
+       return 0;
+}
 
-       DP(BNX2X_MSG_MCP, "starting per-function init port is %x\n", func);
+static int bnx2x_init_port(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+       u32 val;
 
-       REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + func*4, 0);
+       DP(BNX2X_MSG_MCP, "starting port init  port %x\n", port);
+
+       REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
 
        /* Port PXP comes here */
        /* Port PXP2 comes here */
-
-       /* Offset is
-        * Port0  0
-        * Port1  384 */
-       i = func * RQ_ONCHIP_AT_PORT_SIZE;
-#ifdef USE_DMAE
-       wb_write[0] = ONCHIP_ADDR1(bnx2x_sp_mapping(bp, context));
-       wb_write[1] = ONCHIP_ADDR2(bnx2x_sp_mapping(bp, context));
-       REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
-#else
-       REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT + i*8,
-                  ONCHIP_ADDR1(bnx2x_sp_mapping(bp, context)));
-       REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT + i*8 + 4,
-                  ONCHIP_ADDR2(bnx2x_sp_mapping(bp, context)));
-#endif
-       REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4, PXP_ONE_ILT(i));
-
 #ifdef BCM_ISCSI
        /* Port0  1
         * Port1  385 */
@@ -4004,30 +4436,9 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
        REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
        REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
 #endif
-
-       /* Port TCM comes here */
-       /* Port UCM comes here */
-       /* Port CCM comes here */
-       bnx2x_init_block(bp, func ? XCM_PORT1_START : XCM_PORT0_START,
-                            func ? XCM_PORT1_END : XCM_PORT0_END);
-
-#ifdef USE_DMAE
-       wb_write[0] = 0;
-       wb_write[1] = 0;
-#endif
-       for (i = 0; i < 32; i++) {
-               REG_WR(bp, QM_REG_BASEADDR + (func*32 + i)*4, 1024 * 4 * i);
-#ifdef USE_DMAE
-               REG_WR_DMAE(bp, QM_REG_PTRTBL + (func*32 + i)*8, wb_write, 2);
-#else
-               REG_WR_IND(bp, QM_REG_PTRTBL + (func*32 + i)*8, 0);
-               REG_WR_IND(bp, QM_REG_PTRTBL + (func*32 + i)*8 + 4, 0);
-#endif
-       }
-       REG_WR(bp, QM_REG_CONNNUM_0 + func*4, 1024/16 - 1);
+       /* Port CMs come here */
 
        /* Port QM comes here */
-
 #ifdef BCM_ISCSI
        REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20);
        REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31);
@@ -4042,31 +4453,32 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
        /* Port CSDM comes here */
        /* Port USDM comes here */
        /* Port XSDM comes here */
-       bnx2x_init_block(bp, func ? TSEM_PORT1_START : TSEM_PORT0_START,
-                            func ? TSEM_PORT1_END : TSEM_PORT0_END);
-       bnx2x_init_block(bp, func ? USEM_PORT1_START : USEM_PORT0_START,
-                            func ? USEM_PORT1_END : USEM_PORT0_END);
-       bnx2x_init_block(bp, func ? CSEM_PORT1_START : CSEM_PORT0_START,
-                            func ? CSEM_PORT1_END : CSEM_PORT0_END);
-       bnx2x_init_block(bp, func ? XSEM_PORT1_START : XSEM_PORT0_START,
-                            func ? XSEM_PORT1_END : XSEM_PORT0_END);
+       bnx2x_init_block(bp, port ? TSEM_PORT1_START : TSEM_PORT0_START,
+                            port ? TSEM_PORT1_END : TSEM_PORT0_END);
+       bnx2x_init_block(bp, port ? USEM_PORT1_START : USEM_PORT0_START,
+                            port ? USEM_PORT1_END : USEM_PORT0_END);
+       bnx2x_init_block(bp, port ? CSEM_PORT1_START : CSEM_PORT0_START,
+                            port ? CSEM_PORT1_END : CSEM_PORT0_END);
+       bnx2x_init_block(bp, port ? XSEM_PORT1_START : XSEM_PORT0_START,
+                            port ? XSEM_PORT1_END : XSEM_PORT0_END);
        /* Port UPB comes here */
-       /* Port XSDM comes here */
-       bnx2x_init_block(bp, func ? PBF_PORT1_START : PBF_PORT0_START,
-                            func ? PBF_PORT1_END : PBF_PORT0_END);
+       /* Port XPB comes here */
+
+       bnx2x_init_block(bp, port ? PBF_PORT1_START : PBF_PORT0_START,
+                            port ? PBF_PORT1_END : PBF_PORT0_END);
 
        /* configure PBF to work without PAUSE mtu 9000 */
-       REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + func*4, 0);
+       REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
 
        /* update threshold */
-       REG_WR(bp, PBF_REG_P0_ARB_THRSH + func*4, (9040/16));
+       REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
        /* update init credit */
-       REG_WR(bp, PBF_REG_P0_INIT_CRD + func*4, (9040/16) + 553 - 22);
+       REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
 
        /* probe changes */
-       REG_WR(bp, PBF_REG_INIT_P0 + func*4, 1);
+       REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
        msleep(5);
-       REG_WR(bp, PBF_REG_INIT_P0 + func*4, 0);
+       REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
 
 #ifdef BCM_ISCSI
        /* tell the searcher where the T2 table is */
@@ -4084,23 +4496,57 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 #endif
        /* Port CDU comes here */
        /* Port CFC comes here */
-       bnx2x_init_block(bp, func ? HC_PORT1_START : HC_PORT0_START,
-                            func ? HC_PORT1_END : HC_PORT0_END);
-       bnx2x_init_block(bp, func ? MISC_AEU_PORT1_START :
+
+       if (CHIP_IS_E1(bp)) {
+               REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+               REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+       }
+       bnx2x_init_block(bp, port ? HC_PORT1_START : HC_PORT0_START,
+                            port ? HC_PORT1_END : HC_PORT0_END);
+
+       bnx2x_init_block(bp, port ? MISC_AEU_PORT1_START :
                                    MISC_AEU_PORT0_START,
-                            func ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END);
+                            port ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END);
+       /* init aeu_mask_attn_func_0/1:
+        *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
+        *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
+        *             bits 4-7 are used for "per vn group attention" */
+       REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4,
+              (IS_E1HMF(bp) ? 0xF7 : 0x7));
+
        /* Port PXPCS comes here */
        /* Port EMAC0 comes here */
        /* Port EMAC1 comes here */
        /* Port DBU comes here */
        /* Port DBG comes here */
-       bnx2x_init_block(bp, func ? NIG_PORT1_START : NIG_PORT0_START,
-                            func ? NIG_PORT1_END : NIG_PORT0_END);
-       REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + func*4, 1);
+       bnx2x_init_block(bp, port ? NIG_PORT1_START : NIG_PORT0_START,
+                            port ? NIG_PORT1_END : NIG_PORT0_END);
+
+       REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
+
+       if (CHIP_IS_E1H(bp)) {
+               u32 wsum;
+               struct cmng_struct_per_port m_cmng_port;
+               int vn;
+
+               /* 0x2 disable e1hov, 0x1 enable */
+               REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
+                      (IS_E1HMF(bp) ? 0x1 : 0x2));
+
+               /* Init RATE SHAPING and FAIRNESS contexts.
+                  Initialize as if there is 10G link. */
+               wsum = bnx2x_calc_vn_wsum(bp);
+               bnx2x_init_port_minmax(bp, (int)wsum, 10000, &m_cmng_port);
+               if (IS_E1HMF(bp))
+                       for (vn = VN_0; vn < E1HVN_MAX; vn++)
+                               bnx2x_init_vn_minmax(bp, 2*vn + port,
+                                       wsum, 10000, &m_cmng_port);
+       }
+
        /* Port MCP comes here */
        /* Port DMAE comes here */
 
-       switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+       switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
        case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
                /* add SPIO 5 to group 0 */
                val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
@@ -4114,48 +4560,150 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 
        bnx2x__link_reset(bp);
 
+       return 0;
+}
+
+#define ILT_PER_FUNC           (768/2)
+#define FUNC_ILT_BASE(func)    (func * ILT_PER_FUNC)
+/* the phys address is shifted right 12 bits and has an added
+   1=valid bit added to the 53rd bit
+   then since this is a wide register(TM)
+   we split it into two 32 bit writes
+ */
+#define ONCHIP_ADDR1(x)                ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
+#define ONCHIP_ADDR2(x)                ((u32)((1 << 20) | ((u64)x >> 44)))
+#define PXP_ONE_ILT(x)         (((x) << 10) | x)
+#define PXP_ILT_RANGE(f, l)    (((l) << 10) | f)
+
+#define CNIC_ILT_LINES         0
+
+static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
+{
+       int reg;
+
+       if (CHIP_IS_E1H(bp))
+               reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
+       else /* E1 */
+               reg = PXP2_REG_RQ_ONCHIP_AT + index*8;
+
+       bnx2x_wb_wr(bp, reg, ONCHIP_ADDR1(addr), ONCHIP_ADDR2(addr));
+}
+
+static int bnx2x_init_func(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
+       int i;
+
+       DP(BNX2X_MSG_MCP, "starting func init  func %x\n", func);
+
+       i = FUNC_ILT_BASE(func);
+
+       bnx2x_ilt_wr(bp, i, bnx2x_sp_mapping(bp, context));
+       if (CHIP_IS_E1H(bp)) {
+               REG_WR(bp, PXP2_REG_RQ_CDU_FIRST_ILT, i);
+               REG_WR(bp, PXP2_REG_RQ_CDU_LAST_ILT, i + CNIC_ILT_LINES);
+       } else /* E1 */
+               REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4,
+                      PXP_ILT_RANGE(i, i + CNIC_ILT_LINES));
+
+
+       if (CHIP_IS_E1H(bp)) {
+               for (i = 0; i < 9; i++)
+                       bnx2x_init_block(bp,
+                                        cm_start[func][i], cm_end[func][i]);
+
+               REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
+               REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
+       }
+
+       /* HC init per function */
+       if (CHIP_IS_E1H(bp)) {
+               REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+
+               REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+               REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+       }
+       bnx2x_init_block(bp, hc_limits[func][0], hc_limits[func][1]);
+
+       if (CHIP_IS_E1H(bp))
+               REG_WR(bp, HC_REG_FUNC_NUM_P0 + port*4, func);
+
        /* Reset PCIE errors for debug */
        REG_WR(bp, 0x2114, 0xffffffff);
        REG_WR(bp, 0x2120, 0xffffffff);
-       REG_WR(bp, 0x2814, 0xffffffff);
 
-       /* !!! move to init_values.h */
-       REG_WR(bp, XSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
-       REG_WR(bp, USDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
-       REG_WR(bp, CSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
-       REG_WR(bp, TSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
+       return 0;
+}
+
+static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
+{
+       int i, rc = 0;
 
-       REG_WR(bp, DBG_REG_PCI_REQ_CREDIT, 0x1);
-       REG_WR(bp, TM_REG_PCIARB_CRDCNT_VAL, 0x1);
-       REG_WR(bp, CDU_REG_CDU_DEBUG, 0x264);
-       REG_WR(bp, CDU_REG_CDU_DEBUG, 0x0);
+       DP(BNX2X_MSG_MCP, "function %d  load_code %x\n",
+          BP_FUNC(bp), load_code);
 
-       bnx2x_gunzip_end(bp);
+       bp->dmae_ready = 0;
+       mutex_init(&bp->dmae_mutex);
+       bnx2x_gunzip_init(bp);
 
-       if (!nomcp) {
-               port = bp->port;
+       switch (load_code) {
+       case FW_MSG_CODE_DRV_LOAD_COMMON:
+               rc = bnx2x_init_common(bp);
+               if (rc)
+                       goto init_hw_err;
+               /* no break */
+
+       case FW_MSG_CODE_DRV_LOAD_PORT:
+               bp->dmae_ready = 1;
+               rc = bnx2x_init_port(bp);
+               if (rc)
+                       goto init_hw_err;
+               /* no break */
+
+       case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+               bp->dmae_ready = 1;
+               rc = bnx2x_init_func(bp);
+               if (rc)
+                       goto init_hw_err;
+               break;
+
+       default:
+               BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
+               break;
+       }
+
+       if (!BP_NOMCP(bp)) {
+               int func = BP_FUNC(bp);
 
                bp->fw_drv_pulse_wr_seq =
-                               (SHMEM_RD(bp, func_mb[port].drv_pulse_mb) &
+                               (SHMEM_RD(bp, func_mb[func].drv_pulse_mb) &
                                 DRV_PULSE_SEQ_MASK);
-               bp->fw_mb = SHMEM_RD(bp, func_mb[port].fw_mb_param);
-               DP(BNX2X_MSG_MCP, "drv_pulse 0x%x  fw_mb 0x%x\n",
-                  bp->fw_drv_pulse_wr_seq, bp->fw_mb);
-       } else {
-               bp->fw_mb = 0;
-       }
+               bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+               DP(BNX2X_MSG_MCP, "drv_pulse 0x%x  func_stx 0x%x\n",
+                  bp->fw_drv_pulse_wr_seq, bp->func_stx);
+       } else
+               bp->func_stx = 0;
 
-       return 0;
+       /* this needs to be done before gunzip end */
+       bnx2x_zero_def_sb(bp);
+       for_each_queue(bp, i)
+               bnx2x_zero_sb(bp, BP_L_ID(bp) + i);
+
+init_hw_err:
+       bnx2x_gunzip_end(bp);
+
+       return rc;
 }
 
 /* send the MCP a request, block until there is a reply */
 static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
 {
-       int port = bp->port;
+       int func = BP_FUNC(bp);
        u32 seq = ++bp->fw_seq;
        u32 rc = 0;
 
-       SHMEM_WR(bp, func_mb[port].drv_mb_header, (command | seq));
+       SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
        DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
 
        /* let the FW do it's magic ... */
@@ -4164,7 +4712,7 @@ static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
        if (CHIP_REV_IS_SLOW(bp))
                msleep(900);
 
-       rc = SHMEM_RD(bp, func_mb[port].fw_mb_header);
+       rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
        DP(BNX2X_MSG_MCP, "read (%x) seq is (%x) from FW MB\n", rc, seq);
 
        /* is this a reply to our command? */
@@ -4229,15 +4777,13 @@ static void bnx2x_free_mem(struct bnx2x *bp)
                               NUM_RCQ_BD);
        }
 
-       BNX2X_FREE(bp->fp);
-
        /* end of fastpath */
 
        BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
-                      (sizeof(struct host_def_status_block)));
+                      sizeof(struct host_def_status_block));
 
        BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
-                      (sizeof(struct bnx2x_slowpath)));
+                      sizeof(struct bnx2x_slowpath));
 
 #ifdef BCM_ISCSI
        BNX2X_PCI_FREE(bp->t1, bp->t1_mapping, 64*1024);
@@ -4273,8 +4819,6 @@ static int bnx2x_alloc_mem(struct bnx2x *bp)
        int i;
 
        /* fastpath */
-       BNX2X_ALLOC(bp->fp, sizeof(struct bnx2x_fastpath) * bp->num_queues);
-
        for_each_queue(bp, i) {
                bnx2x_fp(bp, i, bp) = bp;
 
@@ -4370,8 +4914,6 @@ static void bnx2x_free_tx_skbs(struct bnx2x *bp)
                u16 sw_prod = fp->tx_pkt_prod;
                u16 sw_cons = fp->tx_pkt_cons;
 
-               BUG_TRAP(fp->tx_buf_ring != NULL);
-
                while (sw_cons != sw_prod) {
                        bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons));
                        sw_cons++;
@@ -4386,8 +4928,6 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
        for_each_queue(bp, j) {
                struct bnx2x_fastpath *fp = &bp->fp[j];
 
-               BUG_TRAP(fp->rx_buf_ring != NULL);
-
                for (i = 0; i < NUM_RX_BD; i++) {
                        struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i];
                        struct sk_buff *skb = rx_buf->skb;
@@ -4414,7 +4954,7 @@ static void bnx2x_free_skbs(struct bnx2x *bp)
 
 static void bnx2x_free_msix_irqs(struct bnx2x *bp)
 {
-       int i;
+       int i, offset = 1;
 
        free_irq(bp->msix_table[0].vector, bp->dev);
        DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
@@ -4422,26 +4962,22 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp)
 
        for_each_queue(bp, i) {
                DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq  "
-                  "state(%x)\n", i, bp->msix_table[i + 1].vector,
+                  "state %x\n", i, bp->msix_table[i + offset].vector,
                   bnx2x_fp(bp, i, state));
 
                if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED)
                        BNX2X_ERR("IRQ of fp #%d being freed while "
                                  "state != closed\n", i);
 
-               free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]);
+               free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]);
        }
-
 }
 
 static void bnx2x_free_irq(struct bnx2x *bp)
 {
-
        if (bp->flags & USING_MSIX_FLAG) {
-
                bnx2x_free_msix_irqs(bp);
                pci_disable_msix(bp->pdev);
-
                bp->flags &= ~USING_MSIX_FLAG;
 
        } else
@@ -4450,87 +4986,87 @@ static void bnx2x_free_irq(struct bnx2x *bp)
 
 static int bnx2x_enable_msix(struct bnx2x *bp)
 {
-
-       int i;
+       int i, rc, offset;
 
        bp->msix_table[0].entry = 0;
-       for_each_queue(bp, i)
-               bp->msix_table[i + 1].entry = i + 1;
+       offset = 1;
+       DP(NETIF_MSG_IFUP, "msix_table[0].entry = 0 (slowpath)\n");
 
-       if (pci_enable_msix(bp->pdev, &bp->msix_table[0],
-                                    bp->num_queues + 1)){
-               BNX2X_LOG("failed to enable MSI-X\n");
-               return -1;
+       for_each_queue(bp, i) {
+               int igu_vec = offset + i + BP_L_ID(bp);
 
+               bp->msix_table[i + offset].entry = igu_vec;
+               DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
+                  "(fastpath #%u)\n", i + offset, igu_vec, i);
        }
 
+       rc = pci_enable_msix(bp->pdev, &bp->msix_table[0],
+                            bp->num_queues + offset);
+       if (rc) {
+               DP(NETIF_MSG_IFUP, "MSI-X is not attainable\n");
+               return -1;
+       }
        bp->flags |= USING_MSIX_FLAG;
 
        return 0;
-
 }
 
-
 static int bnx2x_req_msix_irqs(struct bnx2x *bp)
 {
-
-       int i, rc;
+       int i, rc, offset = 1;
 
        rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0,
                         bp->dev->name, bp->dev);
-
        if (rc) {
                BNX2X_ERR("request sp irq failed\n");
                return -EBUSY;
        }
 
        for_each_queue(bp, i) {
-               rc = request_irq(bp->msix_table[i + 1].vector,
+               rc = request_irq(bp->msix_table[i + offset].vector,
                                 bnx2x_msix_fp_int, 0,
                                 bp->dev->name, &bp->fp[i]);
-
                if (rc) {
-                       BNX2X_ERR("request fp #%d irq failed  "
-                                 "rc %d\n", i, rc);
+                       BNX2X_ERR("request fp #%d irq failed  rc %d\n",
+                                 i + offset, rc);
                        bnx2x_free_msix_irqs(bp);
                        return -EBUSY;
                }
 
                bnx2x_fp(bp, i, state) = BNX2X_FP_STATE_IRQ;
-
        }
 
        return 0;
-
 }
 
 static int bnx2x_req_irq(struct bnx2x *bp)
 {
+       int rc;
 
-       int rc = request_irq(bp->pdev->irq, bnx2x_interrupt,
-                            IRQF_SHARED, bp->dev->name, bp->dev);
+       rc = request_irq(bp->pdev->irq, bnx2x_interrupt, IRQF_SHARED,
+                        bp->dev->name, bp->dev);
        if (!rc)
                bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ;
 
        return rc;
-
 }
 
 /*
  * Init service functions
  */
 
-static void bnx2x_set_mac_addr(struct bnx2x *bp)
+static void bnx2x_set_mac_addr_e1(struct bnx2x *bp)
 {
        struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
+       int port = BP_PORT(bp);
 
        /* CAM allocation
         * unicasts 0-31:port0 32-63:port1
         * multicast 64-127:port0 128-191:port1
         */
        config->hdr.length_6b = 2;
-       config->hdr.offset = bp->port ? 31 : 0;
-       config->hdr.reserved0 = 0;
+       config->hdr.offset = port ? 31 : 0;
+       config->hdr.client_id = BP_CL_ID(bp);
        config->hdr.reserved1 = 0;
 
        /* primary MAC */
@@ -4540,7 +5076,7 @@ static void bnx2x_set_mac_addr(struct bnx2x *bp)
                                        swab16(*(u16 *)&bp->dev->dev_addr[2]);
        config->config_table[0].cam_entry.lsb_mac_addr =
                                        swab16(*(u16 *)&bp->dev->dev_addr[4]);
-       config->config_table[0].cam_entry.flags = cpu_to_le16(bp->port);
+       config->config_table[0].cam_entry.flags = cpu_to_le16(port);
        config->config_table[0].target_table_entry.flags = 0;
        config->config_table[0].target_table_entry.client_id = 0;
        config->config_table[0].target_table_entry.vlan_id = 0;
@@ -4554,7 +5090,7 @@ static void bnx2x_set_mac_addr(struct bnx2x *bp)
        config->config_table[1].cam_entry.msb_mac_addr = 0xffff;
        config->config_table[1].cam_entry.middle_mac_addr = 0xffff;
        config->config_table[1].cam_entry.lsb_mac_addr = 0xffff;
-       config->config_table[1].cam_entry.flags = cpu_to_le16(bp->port);
+       config->config_table[1].cam_entry.flags = cpu_to_le16(port);
        config->config_table[1].target_table_entry.flags =
                                TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST;
        config->config_table[1].target_table_entry.client_id = 0;
@@ -4565,64 +5101,105 @@ static void bnx2x_set_mac_addr(struct bnx2x *bp)
                      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
 }
 
+static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp)
+{
+       struct mac_configuration_cmd_e1h *config =
+               (struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config);
+
+       if (bp->state != BNX2X_STATE_OPEN) {
+               DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
+               return;
+       }
+
+       /* CAM allocation for E1H
+        * unicasts: by func number
+        * multicast: 20+FUNC*20, 20 each
+        */
+       config->hdr.length_6b = 1;
+       config->hdr.offset = BP_FUNC(bp);
+       config->hdr.client_id = BP_CL_ID(bp);
+       config->hdr.reserved1 = 0;
+
+       /* primary MAC */
+       config->config_table[0].msb_mac_addr =
+                                       swab16(*(u16 *)&bp->dev->dev_addr[0]);
+       config->config_table[0].middle_mac_addr =
+                                       swab16(*(u16 *)&bp->dev->dev_addr[2]);
+       config->config_table[0].lsb_mac_addr =
+                                       swab16(*(u16 *)&bp->dev->dev_addr[4]);
+       config->config_table[0].client_id = BP_L_ID(bp);
+       config->config_table[0].vlan_id = 0;
+       config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov);
+       config->config_table[0].flags = BP_PORT(bp);
+
+       DP(NETIF_MSG_IFUP, "setting MAC (%04x:%04x:%04x)  E1HOV %d  CLID %d\n",
+          config->config_table[0].msb_mac_addr,
+          config->config_table[0].middle_mac_addr,
+          config->config_table[0].lsb_mac_addr, bp->e1hov, BP_L_ID(bp));
+
+       bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+                     U64_HI(bnx2x_sp_mapping(bp, mac_config)),
+                     U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+}
+
 static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
                             int *state_p, int poll)
 {
        /* can take a while if any port is running */
-       int timeout = 500;
+       int cnt = 500;
 
        DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
           poll ? "polling" : "waiting", state, idx);
 
        might_sleep();
-
-       while (timeout) {
-
+       while (cnt--) {
                if (poll) {
                        bnx2x_rx_int(bp->fp, 10);
-                       /* If index is different from 0
-                        * The reply for some commands will
+                       /* if index is different from 0
+                        * the reply for some commands will
                         * be on the none default queue
                         */
                        if (idx)
                                bnx2x_rx_int(&bp->fp[idx], 10);
                }
-
-               mb(); /* state is changed by bnx2x_sp_event()*/
+               mb(); /* state is changed by bnx2x_sp_event() */
 
                if (*state_p == state)
                        return 0;
 
-               timeout--;
                msleep(1);
-
        }
 
        /* timeout! */
        BNX2X_ERR("timeout %s for state %x on IDX [%d]\n",
                  poll ? "polling" : "waiting", state, idx);
+#ifdef BNX2X_STOP_ON_ERROR
+       bnx2x_panic();
+#endif
 
        return -EBUSY;
 }
 
 static int bnx2x_setup_leading(struct bnx2x *bp)
 {
+       int rc;
 
        /* reset IGU state */
-       bnx2x_ack_sb(bp, DEF_SB_ID, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+       bnx2x_ack_sb(bp, bp->fp[0].sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
 
        /* SETUP ramrod */
        bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_SETUP, 0, 0, 0, 0);
 
-       return bnx2x_wait_ramrod(bp, BNX2X_STATE_OPEN, 0, &(bp->state), 0);
+       /* Wait for completion */
+       rc = bnx2x_wait_ramrod(bp, BNX2X_STATE_OPEN, 0, &(bp->state), 0);
 
+       return rc;
 }
 
 static int bnx2x_setup_multi(struct bnx2x *bp, int index)
 {
-
        /* reset IGU state */
-       bnx2x_ack_sb(bp, index, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+       bnx2x_ack_sb(bp, bp->fp[index].sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
 
        /* SETUP ramrod */
        bp->fp[index].state = BNX2X_FP_STATE_OPENING;
@@ -4631,82 +5208,107 @@ static int bnx2x_setup_multi(struct bnx2x *bp, int index)
        /* Wait for completion */
        return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index,
                                 &(bp->fp[index].state), 0);
-
 }
 
-
 static int bnx2x_poll(struct napi_struct *napi, int budget);
 static void bnx2x_set_rx_mode(struct net_device *dev);
 
-static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
+/* must be called with rtnl_lock */
+static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
        u32 load_code;
-       int i;
+       int i, rc;
+
+#ifdef BNX2X_STOP_ON_ERROR
+       if (unlikely(bp->panic))
+               return -EPERM;
+#endif
 
        bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
 
-       /* Send LOAD_REQUEST command to MCP.
-          Returns the type of LOAD command: if it is the
-          first port to be initialized common blocks should be
-          initialized, otherwise - not.
+       /* Send LOAD_REQUEST command to MCP
+          Returns the type of LOAD command:
+          if it is the first port to be initialized
+          common blocks should be initialized, otherwise - not
        */
-       if (!nomcp) {
+       if (!BP_NOMCP(bp)) {
                load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
                if (!load_code) {
                        BNX2X_ERR("MCP response failure, unloading\n");
                        return -EBUSY;
                }
-               if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
-                       BNX2X_ERR("MCP refused load request, unloading\n");
+               if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED)
                        return -EBUSY; /* other port in diagnostic mode */
-               }
+
        } else {
-               load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
+               DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
+                  load_count[0], load_count[1], load_count[2]);
+               load_count[0]++;
+               load_count[1 + BP_PORT(bp)]++;
+               DP(NETIF_MSG_IFUP, "NO MCP new load counts       %d, %d, %d\n",
+                  load_count[0], load_count[1], load_count[2]);
+               if (load_count[0] == 1)
+                       load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
+               else if (load_count[1 + BP_PORT(bp)] == 1)
+                       load_code = FW_MSG_CODE_DRV_LOAD_PORT;
+               else
+                       load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
        }
 
-       /* if we can't use msix we only need one fp,
-        * so try to enable msix with the requested number of fp's
+       if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+           (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
+               bp->port.pmf = 1;
+       else
+               bp->port.pmf = 0;
+       DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+
+       /* if we can't use MSI-X we only need one fp,
+        * so try to enable MSI-X with the requested number of fp's
         * and fallback to inta with one fp
         */
-       if (req_irq) {
-               if (use_inta) {
+       if (use_inta) {
+               bp->num_queues = 1;
+
+       } else {
+               if ((use_multi > 1) && (use_multi <= BP_MAX_QUEUES(bp)))
+                       /* user requested number */
+                       bp->num_queues = use_multi;
+
+               else if (use_multi)
+                       bp->num_queues = min_t(u32, num_online_cpus(),
+                                              BP_MAX_QUEUES(bp));
+               else
                        bp->num_queues = 1;
-               } else {
-                       if ((use_multi > 1) && (use_multi <= 16))
-                               /* user requested number */
-                               bp->num_queues = use_multi;
-                       else if (use_multi == 1)
-                               bp->num_queues = num_online_cpus();
-                       else
-                               bp->num_queues = 1;
-
-                       if (bnx2x_enable_msix(bp)) {
-                               /* failed to enable msix */
-                               bp->num_queues = 1;
-                               if (use_multi)
-                                       BNX2X_ERR("Multi requested but failed"
-                                                 " to enable MSI-X\n");
-                       }
+
+               if (bnx2x_enable_msix(bp)) {
+                       /* failed to enable MSI-X */
+                       bp->num_queues = 1;
+                       if (use_multi)
+                               BNX2X_ERR("Multi requested but failed"
+                                         " to enable MSI-X\n");
                }
        }
-
-       DP(NETIF_MSG_IFUP, "set number of queues to %d\n", bp->num_queues);
+       DP(NETIF_MSG_IFUP,
+          "set number of queues to %d\n", bp->num_queues);
 
        if (bnx2x_alloc_mem(bp))
                return -ENOMEM;
 
-       if (req_irq) {
-               if (bp->flags & USING_MSIX_FLAG) {
-                       if (bnx2x_req_msix_irqs(bp)) {
-                               pci_disable_msix(bp->pdev);
-                               goto load_error;
-                       }
+       /* Disable interrupt handling until HW is initialized */
+       atomic_set(&bp->intr_sem, 1);
 
-               } else {
-                       if (bnx2x_req_irq(bp)) {
-                               BNX2X_ERR("IRQ request failed, aborting\n");
-                               goto load_error;
-                       }
+       if (bp->flags & USING_MSIX_FLAG) {
+               rc = bnx2x_req_msix_irqs(bp);
+               if (rc) {
+                       pci_disable_msix(bp->pdev);
+                       goto load_error;
+               }
+       } else {
+               bnx2x_ack_int(bp);
+               rc = bnx2x_req_irq(bp);
+               if (rc) {
+                       BNX2X_ERR("IRQ request failed, aborting\n");
+                       goto load_error;
                }
        }
 
@@ -4714,26 +5316,25 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
                netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
                               bnx2x_poll, 128);
 
-
        /* Initialize HW */
-       if (bnx2x_function_init(bp,
-                               (load_code == FW_MSG_CODE_DRV_LOAD_COMMON))) {
+       rc = bnx2x_init_hw(bp, load_code);
+       if (rc) {
                BNX2X_ERR("HW init failed, aborting\n");
                goto load_error;
        }
 
-
+       /* Enable interrupt handling */
        atomic_set(&bp->intr_sem, 0);
 
-
        /* Setup NIC internals and enable interrupts */
        bnx2x_nic_init(bp);
 
        /* Send LOAD_DONE command to MCP */
-       if (!nomcp) {
+       if (!BP_NOMCP(bp)) {
                load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
                if (!load_code) {
                        BNX2X_ERR("MCP response failure, unloading\n");
+                       rc = -EBUSY;
                        goto load_int_disable;
                }
        }
@@ -4745,33 +5346,68 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
        for_each_queue(bp, i)
                napi_enable(&bnx2x_fp(bp, i, napi));
 
-       if (bnx2x_setup_leading(bp))
+       rc = bnx2x_setup_leading(bp);
+       if (rc) {
+#ifdef BNX2X_STOP_ON_ERROR
+               bp->panic = 1;
+#endif
                goto load_stop_netif;
+       }
 
-       for_each_nondefault_queue(bp, i)
-               if (bnx2x_setup_multi(bp, i))
-                       goto load_stop_netif;
+       if (CHIP_IS_E1H(bp))
+               if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
+                       BNX2X_ERR("!!!  mf_cfg function disabled\n");
+                       bp->state = BNX2X_STATE_DISABLED;
+               }
 
-       bnx2x_set_mac_addr(bp);
+       if (bp->state == BNX2X_STATE_OPEN)
+               for_each_nondefault_queue(bp, i) {
+                       rc = bnx2x_setup_multi(bp, i);
+                       if (rc)
+                               goto load_stop_netif;
+               }
 
-       bnx2x_initial_phy_init(bp);
+       if (CHIP_IS_E1(bp))
+               bnx2x_set_mac_addr_e1(bp);
+       else
+               bnx2x_set_mac_addr_e1h(bp);
+
+       if (bp->port.pmf)
+               bnx2x_initial_phy_init(bp);
 
        /* Start fast path */
-       if (req_irq) { /* IRQ is only requested from bnx2x_open */
+       switch (load_mode) {
+       case LOAD_NORMAL:
+               /* Tx queue should be only reenabled */
+               netif_wake_queue(bp->dev);
+               bnx2x_set_rx_mode(bp->dev);
+               break;
+
+       case LOAD_OPEN:
+               /* IRQ is only requested from bnx2x_open */
                netif_start_queue(bp->dev);
+               bnx2x_set_rx_mode(bp->dev);
                if (bp->flags & USING_MSIX_FLAG)
                        printk(KERN_INFO PFX "%s: using MSI-X\n",
                               bp->dev->name);
+               break;
 
-       /* Otherwise Tx queue should be only reenabled */
-       } else if (netif_running(bp->dev)) {
-               netif_wake_queue(bp->dev);
+       case LOAD_DIAG:
                bnx2x_set_rx_mode(bp->dev);
+               bp->state = BNX2X_STATE_DIAG;
+               break;
+
+       default:
+               break;
        }
 
+       if (!bp->port.pmf)
+               bnx2x__link_status_update(bp);
+
        /* start the timer */
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 
+
        return 0;
 
 load_stop_netif:
@@ -4781,7 +5417,7 @@ load_stop_netif:
 load_int_disable:
        bnx2x_int_disable_sync(bp);
 
-       bnx2x_free_skbs(bp);
+       /* Release IRQs */
        bnx2x_free_irq(bp);
 
 load_error:
@@ -4789,95 +5425,50 @@ load_error:
 
        /* TBD we really need to reset the chip
           if we want to recover from this */
-       return -EBUSY;
-}
-
-
-static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
-{
-       int port = bp->port;
-#ifdef USE_DMAE
-       u32 wb_write[2];
-#endif
-       int base, i;
-
-       DP(NETIF_MSG_IFDOWN, "reset called with code %x\n", reset_code);
-
-       /* Do not rcv packets to BRB */
-       REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + port*4, 0x0);
-       /* Do not direct rcv packets that are not for MCP to the BRB */
-       REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
-                          NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
-
-       /* Configure IGU and AEU */
-       REG_WR(bp, HC_REG_CONFIG_0 + port*4, 0x1000);
-       REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, 0);
-
-       /* TODO: Close Doorbell port? */
-
-       /* Clear ILT */
-#ifdef USE_DMAE
-       wb_write[0] = 0;
-       wb_write[1] = 0;
-#endif
-       base = port * RQ_ONCHIP_AT_PORT_SIZE;
-       for (i = base; i < base + RQ_ONCHIP_AT_PORT_SIZE; i++) {
-#ifdef USE_DMAE
-               REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
-#else
-               REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT, 0);
-               REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT + 4, 0);
-#endif
-       }
-
-       if (reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) {
-               /* reset_common */
-               REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-                      0xd3ffff7f);
-               REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-                      0x1403);
-       }
+       return rc;
 }
 
 static int bnx2x_stop_multi(struct bnx2x *bp, int index)
 {
-
        int rc;
 
        /* halt the connection */
        bp->fp[index].state = BNX2X_FP_STATE_HALTING;
        bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, 0, 0);
 
-
+       /* Wait for completion */
        rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index,
-                                      &(bp->fp[index].state), 1);
+                              &(bp->fp[index].state), 1);
        if (rc) /* timeout */
                return rc;
 
        /* delete cfc entry */
        bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CFC_DEL, index, 0, 0, 1);
 
-       return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
-                                &(bp->fp[index].state), 1);
-
+       /* Wait for completion */
+       rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
+                              &(bp->fp[index].state), 1);
+       return rc;
 }
 
-
 static void bnx2x_stop_leading(struct bnx2x *bp)
 {
        u16 dsb_sp_prod_idx;
        /* if the other port is handling traffic,
           this can take a lot of time */
-       int timeout = 500;
+       int cnt = 500;
+       int rc;
 
        might_sleep();
 
        /* Send HALT ramrod */
        bp->fp[0].state = BNX2X_FP_STATE_HALTING;
-       bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, 0, 0, 0, 0);
+       bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, 0, 0, BP_CL_ID(bp), 0);
 
-       if (bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
-                              &(bp->fp[0].state), 1))
+       /* Wait for completion */
+       rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
+                              &(bp->fp[0].state), 1);
+       if (rc) /* timeout */
                return;
 
        dsb_sp_prod_idx = *bp->dsb_sp_prod;
@@ -4889,29 +5480,110 @@ static void bnx2x_stop_leading(struct bnx2x *bp)
           we are going to reset the chip anyway
           so there is not much to do if this times out
         */
-       while ((dsb_sp_prod_idx == *bp->dsb_sp_prod) && timeout) {
-               timeout--;
+       while (dsb_sp_prod_idx == *bp->dsb_sp_prod) {
                msleep(1);
-       }
-       if (!timeout) {
-               DP(NETIF_MSG_IFDOWN, "timeout polling for completion "
-                  "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
-                  *bp->dsb_sp_prod, dsb_sp_prod_idx);
+               if (!cnt) {
+                       DP(NETIF_MSG_IFDOWN, "timeout waiting for port del "
+                          "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
+                          *bp->dsb_sp_prod, dsb_sp_prod_idx);
+#ifdef BNX2X_STOP_ON_ERROR
+                       bnx2x_panic();
+#endif
+                       break;
+               }
+               cnt--;
        }
        bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
        bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
 }
 
+static void bnx2x_reset_func(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
+       int base, i;
+
+       /* Configure IGU */
+       REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+       REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+
+       REG_WR(bp, HC_REG_CONFIG_0 + port*4, 0x1000);
+
+       /* Clear ILT */
+       base = FUNC_ILT_BASE(func);
+       for (i = base; i < base + ILT_PER_FUNC; i++)
+               bnx2x_ilt_wr(bp, i, 0);
+}
+
+static void bnx2x_reset_port(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+       u32 val;
+
+       REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
+
+       /* Do not rcv packets to BRB */
+       REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + port*4, 0x0);
+       /* Do not direct rcv packets that are not for MCP to the BRB */
+       REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
+                          NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
+
+       /* Configure AEU */
+       REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, 0);
+
+       msleep(100);
+       /* Check for BRB port occupancy */
+       val = REG_RD(bp, BRB1_REG_PORT_NUM_OCC_BLOCKS_0 + port*4);
+       if (val)
+               DP(NETIF_MSG_IFDOWN,
+                  "BRB1 is not empty  %d blooks are occupied\n", val);
+
+       /* TODO: Close Doorbell port? */
+}
+
+static void bnx2x_reset_common(struct bnx2x *bp)
+{
+       /* reset_common */
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+              0xd3ffff7f);
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
+}
+
+static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
+{
+       DP(BNX2X_MSG_MCP, "function %d  reset_code %x\n",
+          BP_FUNC(bp), reset_code);
+
+       switch (reset_code) {
+       case FW_MSG_CODE_DRV_UNLOAD_COMMON:
+               bnx2x_reset_port(bp);
+               bnx2x_reset_func(bp);
+               bnx2x_reset_common(bp);
+               break;
+
+       case FW_MSG_CODE_DRV_UNLOAD_PORT:
+               bnx2x_reset_port(bp);
+               bnx2x_reset_func(bp);
+               break;
+
+       case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
+               bnx2x_reset_func(bp);
+               break;
 
-static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq)
+       default:
+               BNX2X_ERR("Unknown reset_code (0x%x) from MCP\n", reset_code);
+               break;
+       }
+}
+
+/* msut be called with rtnl_lock */
+static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 {
        u32 reset_code = 0;
-       int i, timeout;
+       int i, cnt;
 
        bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
 
-       del_timer_sync(&bp->timer);
-
        bp->rx_mode = BNX2X_RX_MODE_NONE;
        bnx2x_set_storm_rx_mode(bp);
 
@@ -4920,21 +5592,44 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq)
                bp->dev->trans_start = jiffies; /* prevent tx timeout */
        }
 
+       del_timer_sync(&bp->timer);
+       SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
+                (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
+
        /* Wait until all fast path tasks complete */
        for_each_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
 
-               timeout = 1000;
-               while (bnx2x_has_work(fp) && (timeout--))
+#ifdef BNX2X_STOP_ON_ERROR
+#ifdef __powerpc64__
+               DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n",
+#else
+               DP(NETIF_MSG_IFDOWN, "fp->tpa_queue_used = 0x%llx\n",
+#endif
+                  fp->tpa_queue_used);
+#endif
+               cnt = 1000;
+               smp_rmb();
+               while (bnx2x_has_work(fp)) {
                        msleep(1);
-               if (!timeout)
-                       BNX2X_ERR("timeout waiting for queue[%d]\n", i);
+                       if (!cnt) {
+                               BNX2X_ERR("timeout waiting for queue[%d]\n",
+                                         i);
+#ifdef BNX2X_STOP_ON_ERROR
+                               bnx2x_panic();
+                               return -EBUSY;
+#else
+                               break;
+#endif
+                       }
+                       cnt--;
+                       smp_rmb();
+               }
        }
 
-       /* Wait until stat ramrod returns and all SP tasks complete */
-       timeout = 1000;
-       while ((bp->stat_pending || (bp->spq_left != MAX_SPQ_PENDING)) &&
-              (timeout--))
+       /* Wait until all slow path tasks complete */
+       cnt = 1000;
+       while ((bp->spq_left != MAX_SPQ_PENDING) && cnt--)
                msleep(1);
 
        for_each_queue(bp, i)
@@ -4942,59 +5637,84 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq)
        /* Disable interrupts after Tx and Rx are disabled on stack level */
        bnx2x_int_disable_sync(bp);
 
+       /* Release IRQs */
+       bnx2x_free_irq(bp);
+
        if (bp->flags & NO_WOL_FLAG)
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
 
        else if (bp->wol) {
-               u32 emac_base = bp->port ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
+               u32 emac_base = BP_PORT(bp) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
                u8 *mac_addr = bp->dev->dev_addr;
-               u32 val = (EMAC_MODE_MPKT | EMAC_MODE_MPKT_RCVD |
-                          EMAC_MODE_ACPI_RCVD);
-
-               EMAC_WR(EMAC_REG_EMAC_MODE, val);
+               u32 val;
 
+               /* The mac address is written to entries 1-4 to
+                  preserve entry 0 which is used by the PMF */
                val = (mac_addr[0] << 8) | mac_addr[1];
-               EMAC_WR(EMAC_REG_EMAC_MAC_MATCH, val);
+               EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + (BP_E1HVN(bp) + 1)*8, val);
 
                val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
                      (mac_addr[4] << 8) | mac_addr[5];
-               EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val);
+               EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + (BP_E1HVN(bp) + 1)*8 + 4,
+                       val);
 
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
 
        } else
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
 
-       /* Close multi and leading connections */
+       /* Close multi and leading connections
+          Completions for ramrods are collected in a synchronous way */
        for_each_nondefault_queue(bp, i)
                if (bnx2x_stop_multi(bp, i))
                        goto unload_error;
 
-       bnx2x_stop_leading(bp);
+       if (CHIP_IS_E1H(bp))
+               REG_WR(bp, NIG_REG_LLH0_FUNC_EN + BP_PORT(bp)*8, 0);
+
+       bnx2x_stop_leading(bp);
+#ifdef BNX2X_STOP_ON_ERROR
+       /* If ramrod completion timed out - break here! */
+       if (bp->panic) {
+               BNX2X_ERR("Stop leading failed!\n");
+               return -EBUSY;
+       }
+#endif
+
        if ((bp->state != BNX2X_STATE_CLOSING_WAIT4_UNLOAD) ||
            (bp->fp[0].state != BNX2X_FP_STATE_CLOSED)) {
-               DP(NETIF_MSG_IFDOWN, "failed to close leading properly!"
-                  "state 0x%x  fp[0].state 0x%x",
+               DP(NETIF_MSG_IFDOWN, "failed to close leading properly!  "
+                  "state 0x%x  fp[0].state 0x%x\n",
                   bp->state, bp->fp[0].state);
        }
 
 unload_error:
-       bnx2x__link_reset(bp);
-
-       if (!nomcp)
+       if (!BP_NOMCP(bp))
                reset_code = bnx2x_fw_command(bp, reset_code);
-       else
-               reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+       else {
+               DP(NETIF_MSG_IFDOWN, "NO MCP load counts      %d, %d, %d\n",
+                  load_count[0], load_count[1], load_count[2]);
+               load_count[0]--;
+               load_count[1 + BP_PORT(bp)]--;
+               DP(NETIF_MSG_IFDOWN, "NO MCP new load counts  %d, %d, %d\n",
+                  load_count[0], load_count[1], load_count[2]);
+               if (load_count[0] == 0)
+                       reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+               else if (load_count[1 + BP_PORT(bp)] == 0)
+                       reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
+               else
+                       reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
+       }
 
-       /* Release IRQs */
-       if (free_irq)
-               bnx2x_free_irq(bp);
+       if ((reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) ||
+           (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
+               bnx2x__link_reset(bp);
 
        /* Reset the chip */
        bnx2x_reset_chip(bp, reset_code);
 
        /* Report UNLOAD_DONE to MCP */
-       if (!nomcp)
+       if (!BP_NOMCP(bp))
                bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
 
        /* Free SKBs and driver internals */
@@ -5008,6 +5728,29 @@ unload_error:
        return 0;
 }
 
+static void bnx2x_reset_task(struct work_struct *work)
+{
+       struct bnx2x *bp = container_of(work, struct bnx2x, reset_task);
+
+#ifdef BNX2X_STOP_ON_ERROR
+       BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
+                 " so reset not done to allow debug dump,\n"
+        KERN_ERR " you will need to reboot when done\n");
+       return;
+#endif
+
+       rtnl_lock();
+
+       if (!netif_running(bp->dev))
+               goto reset_task_exit;
+
+       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+       bnx2x_nic_load(bp, LOAD_NORMAL);
+
+reset_task_exit:
+       rtnl_unlock();
+}
+
 /* end of nic load/unload */
 
 /* ethtool_ops */
@@ -5016,9 +5759,139 @@ unload_error:
  * Init service functions
  */
 
-static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
+static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
+{
+       u32 val;
+
+       /* Check if there is any driver already loaded */
+       val = REG_RD(bp, MISC_REG_UNPREPARED);
+       if (val == 0x1) {
+               /* Check if it is the UNDI driver
+                * UNDI driver initializes CID offset for normal bell to 0x7
+                */
+               val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
+               if (val == 0x7) {
+                       u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
+                       /* save our func and fw_seq */
+                       int func = BP_FUNC(bp);
+                       u16 fw_seq = bp->fw_seq;
+
+                       BNX2X_DEV_INFO("UNDI is active! reset device\n");
+
+                       /* try unload UNDI on port 0 */
+                       bp->func = 0;
+                       bp->fw_seq = (SHMEM_RD(bp,
+                                            func_mb[bp->func].drv_mb_header) &
+                                     DRV_MSG_SEQ_NUMBER_MASK);
+
+                       reset_code = bnx2x_fw_command(bp, reset_code);
+                       bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+
+                       /* if UNDI is loaded on the other port */
+                       if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
+
+                               bp->func = 1;
+                               bp->fw_seq = (SHMEM_RD(bp,
+                                            func_mb[bp->func].drv_mb_header) &
+                                             DRV_MSG_SEQ_NUMBER_MASK);
+
+                               bnx2x_fw_command(bp,
+                                            DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS);
+                               bnx2x_fw_command(bp,
+                                                DRV_MSG_CODE_UNLOAD_DONE);
+
+                               /* restore our func and fw_seq */
+                               bp->func = func;
+                               bp->fw_seq = fw_seq;
+                       }
+
+                       /* reset device */
+                       REG_WR(bp,
+                              GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+                              0xd3ffff7f);
+                       REG_WR(bp,
+                              GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+                              0x1403);
+               }
+       }
+}
+
+static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
+{
+       u32 val, val2, val3, val4, id;
+
+       /* Get the chip revision id and number. */
+       /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
+       val = REG_RD(bp, MISC_REG_CHIP_NUM);
+       id = ((val & 0xffff) << 16);
+       val = REG_RD(bp, MISC_REG_CHIP_REV);
+       id |= ((val & 0xf) << 12);
+       val = REG_RD(bp, MISC_REG_CHIP_METAL);
+       id |= ((val & 0xff) << 4);
+       REG_RD(bp, MISC_REG_BOND_ID);
+       id |= (val & 0xf);
+       bp->common.chip_id = id;
+       bp->link_params.chip_id = bp->common.chip_id;
+       BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
+
+       val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
+       bp->common.flash_size = (NVRAM_1MB_SIZE <<
+                                (val & MCPR_NVM_CFG4_FLASH_SIZE));
+       BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
+                      bp->common.flash_size, bp->common.flash_size);
+
+       bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
+       bp->link_params.shmem_base = bp->common.shmem_base;
+       BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base);
+
+       if (!bp->common.shmem_base ||
+           (bp->common.shmem_base < 0xA0000) ||
+           (bp->common.shmem_base >= 0xC0000)) {
+               BNX2X_DEV_INFO("MCP not active\n");
+               bp->flags |= NO_MCP_FLAG;
+               return;
+       }
+
+       val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
+       if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+               != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+               BNX2X_ERR("BAD MCP validity signature\n");
+
+       bp->common.hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
+       bp->common.board = SHMEM_RD(bp, dev_info.shared_hw_config.board);
+
+       BNX2X_DEV_INFO("hw_config 0x%08x  board 0x%08x\n",
+                      bp->common.hw_config, bp->common.board);
+
+       bp->link_params.hw_led_mode = ((bp->common.hw_config &
+                                       SHARED_HW_CFG_LED_MODE_MASK) >>
+                                      SHARED_HW_CFG_LED_MODE_SHIFT);
+
+       val = SHMEM_RD(bp, dev_info.bc_rev) >> 8;
+       bp->common.bc_ver = val;
+       BNX2X_DEV_INFO("bc_ver %X\n", val);
+       if (val < BNX2X_BC_VER) {
+               /* for now only warn
+                * later we might need to enforce this */
+               BNX2X_ERR("This driver needs bc_ver %X but found %X,"
+                         " please upgrade BC\n", BNX2X_BC_VER, val);
+       }
+       BNX2X_DEV_INFO("%sWoL Capable\n",
+                      (bp->flags & NO_WOL_FLAG)? "Not " : "");
+
+       val = SHMEM_RD(bp, dev_info.shared_hw_config.part_num);
+       val2 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[4]);
+       val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]);
+       val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]);
+
+       printk(KERN_INFO PFX "part number %X-%X-%X-%X\n",
+              val, val2, val3, val4);
+}
+
+static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
+                                                   u32 switch_cfg)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        u32 ext_phy_type;
 
        switch (switch_cfg) {
@@ -5032,31 +5905,33 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10baseT_Half |
-                                         SUPPORTED_10baseT_Full |
-                                         SUPPORTED_100baseT_Half |
-                                         SUPPORTED_100baseT_Full |
-                                         SUPPORTED_1000baseT_Full |
-                                         SUPPORTED_2500baseX_Full |
-                                         SUPPORTED_TP | SUPPORTED_FIBRE |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10baseT_Half |
+                                              SUPPORTED_10baseT_Full |
+                                              SUPPORTED_100baseT_Half |
+                                              SUPPORTED_100baseT_Full |
+                                              SUPPORTED_1000baseT_Full |
+                                              SUPPORTED_2500baseX_Full |
+                                              SUPPORTED_TP |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Autoneg |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (5482)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10baseT_Half |
-                                         SUPPORTED_10baseT_Full |
-                                         SUPPORTED_100baseT_Half |
-                                         SUPPORTED_100baseT_Full |
-                                         SUPPORTED_1000baseT_Full |
-                                         SUPPORTED_TP | SUPPORTED_FIBRE |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10baseT_Half |
+                                              SUPPORTED_10baseT_Full |
+                                              SUPPORTED_100baseT_Half |
+                                              SUPPORTED_100baseT_Full |
+                                              SUPPORTED_1000baseT_Full |
+                                              SUPPORTED_TP |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Autoneg |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                default:
@@ -5066,9 +5941,9 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
                        return;
                }
 
-               bp->phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
-                                     port*0x10);
-               BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->phy_addr);
+               bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
+                                          port*0x10);
+               BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
                break;
 
        case SWITCH_CFG_10G:
@@ -5081,75 +5956,75 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10baseT_Half |
-                                         SUPPORTED_10baseT_Full |
-                                         SUPPORTED_100baseT_Half |
-                                         SUPPORTED_100baseT_Full |
-                                         SUPPORTED_1000baseT_Full |
-                                         SUPPORTED_2500baseX_Full |
-                                         SUPPORTED_10000baseT_Full |
-                                         SUPPORTED_TP | SUPPORTED_FIBRE |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10baseT_Half |
+                                              SUPPORTED_10baseT_Full |
+                                              SUPPORTED_100baseT_Half |
+                                              SUPPORTED_100baseT_Full |
+                                              SUPPORTED_1000baseT_Full |
+                                              SUPPORTED_2500baseX_Full |
+                                              SUPPORTED_10000baseT_Full |
+                                              SUPPORTED_TP |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Autoneg |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n",
-                                       ext_phy_type);
+                                      ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10000baseT_Full |
-                                         SUPPORTED_FIBRE |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10000baseT_Full |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10000baseT_Full |
-                                         SUPPORTED_1000baseT_Full |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_FIBRE |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10000baseT_Full |
+                                              SUPPORTED_1000baseT_Full |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10000baseT_Full |
-                                         SUPPORTED_1000baseT_Full |
-                                         SUPPORTED_FIBRE |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10000baseT_Full |
+                                              SUPPORTED_1000baseT_Full |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Autoneg |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10000baseT_Full |
-                                         SUPPORTED_2500baseX_Full |
-                                         SUPPORTED_1000baseT_Full |
-                                         SUPPORTED_FIBRE |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10000baseT_Full |
+                                              SUPPORTED_2500baseX_Full |
+                                              SUPPORTED_1000baseT_Full |
+                                              SUPPORTED_FIBRE |
+                                              SUPPORTED_Autoneg |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
                        BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
                                       ext_phy_type);
 
-                       bp->supported |= (SUPPORTED_10000baseT_Full |
-                                         SUPPORTED_TP |
-                                         SUPPORTED_Autoneg |
-                                         SUPPORTED_Pause |
-                                         SUPPORTED_Asym_Pause);
+                       bp->port.supported |= (SUPPORTED_10000baseT_Full |
+                                              SUPPORTED_TP |
+                                              SUPPORTED_Autoneg |
+                                              SUPPORTED_Pause |
+                                              SUPPORTED_Asym_Pause);
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
@@ -5164,61 +6039,61 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
                        return;
                }
 
-               bp->phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
-                                     port*0x18);
-               BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->phy_addr);
+               bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
+                                          port*0x18);
+               BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
 
                break;
 
        default:
                BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
-                         bp->link_config);
+                         bp->port.link_config);
                return;
        }
-       bp->link_params.phy_addr = bp->phy_addr;
+       bp->link_params.phy_addr = bp->port.phy_addr;
 
        /* mask what we support according to speed_cap_mask */
        if (!(bp->link_params.speed_cap_mask &
                                PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
-               bp->supported &= ~SUPPORTED_10baseT_Half;
+               bp->port.supported &= ~SUPPORTED_10baseT_Half;
 
        if (!(bp->link_params.speed_cap_mask &
                                PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
-               bp->supported &= ~SUPPORTED_10baseT_Full;
+               bp->port.supported &= ~SUPPORTED_10baseT_Full;
 
        if (!(bp->link_params.speed_cap_mask &
                                PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
-               bp->supported &= ~SUPPORTED_100baseT_Half;
+               bp->port.supported &= ~SUPPORTED_100baseT_Half;
 
        if (!(bp->link_params.speed_cap_mask &
                                PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
-               bp->supported &= ~SUPPORTED_100baseT_Full;
+               bp->port.supported &= ~SUPPORTED_100baseT_Full;
 
        if (!(bp->link_params.speed_cap_mask &
                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
-               bp->supported &= ~(SUPPORTED_1000baseT_Half |
-                                  SUPPORTED_1000baseT_Full);
+               bp->port.supported &= ~(SUPPORTED_1000baseT_Half |
+                                       SUPPORTED_1000baseT_Full);
 
        if (!(bp->link_params.speed_cap_mask &
                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
-               bp->supported &= ~SUPPORTED_2500baseX_Full;
+               bp->port.supported &= ~SUPPORTED_2500baseX_Full;
 
        if (!(bp->link_params.speed_cap_mask &
                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
-               bp->supported &= ~SUPPORTED_10000baseT_Full;
+               bp->port.supported &= ~SUPPORTED_10000baseT_Full;
 
-       BNX2X_DEV_INFO("supported 0x%x\n", bp->supported);
+       BNX2X_DEV_INFO("supported 0x%x\n", bp->port.supported);
 }
 
-static void bnx2x_link_settings_requested(struct bnx2x *bp)
+static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 {
        bp->link_params.req_duplex = DUPLEX_FULL;
 
-       switch (bp->link_config & PORT_FEATURE_LINK_SPEED_MASK) {
+       switch (bp->port.link_config & PORT_FEATURE_LINK_SPEED_MASK) {
        case PORT_FEATURE_LINK_SPEED_AUTO:
-               if (bp->supported & SUPPORTED_Autoneg) {
+               if (bp->port.supported & SUPPORTED_Autoneg) {
                        bp->link_params.req_line_speed = SPEED_AUTO_NEG;
-                       bp->advertising = bp->supported;
+                       bp->port.advertising = bp->port.supported;
                } else {
                        u32 ext_phy_type =
                            XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
@@ -5229,7 +6104,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) {
                                /* force 10G, no AN */
                                bp->link_params.req_line_speed = SPEED_10000;
-                               bp->advertising =
+                               bp->port.advertising =
                                                (ADVERTISED_10000baseT_Full |
                                                 ADVERTISED_FIBRE);
                                break;
@@ -5237,98 +6112,98 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  Autoneg not supported\n",
-                                 bp->link_config);
+                                 bp->port.link_config);
                        return;
                }
                break;
 
        case PORT_FEATURE_LINK_SPEED_10M_FULL:
-               if (bp->supported & SUPPORTED_10baseT_Full) {
+               if (bp->port.supported & SUPPORTED_10baseT_Full) {
                        bp->link_params.req_line_speed = SPEED_10;
-                       bp->advertising = (ADVERTISED_10baseT_Full |
-                                          ADVERTISED_TP);
+                       bp->port.advertising = (ADVERTISED_10baseT_Full |
+                                               ADVERTISED_TP);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
                break;
 
        case PORT_FEATURE_LINK_SPEED_10M_HALF:
-               if (bp->supported & SUPPORTED_10baseT_Half) {
+               if (bp->port.supported & SUPPORTED_10baseT_Half) {
                        bp->link_params.req_line_speed = SPEED_10;
                        bp->link_params.req_duplex = DUPLEX_HALF;
-                       bp->advertising = (ADVERTISED_10baseT_Half |
-                                          ADVERTISED_TP);
+                       bp->port.advertising = (ADVERTISED_10baseT_Half |
+                                               ADVERTISED_TP);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
                break;
 
        case PORT_FEATURE_LINK_SPEED_100M_FULL:
-               if (bp->supported & SUPPORTED_100baseT_Full) {
+               if (bp->port.supported & SUPPORTED_100baseT_Full) {
                        bp->link_params.req_line_speed = SPEED_100;
-                       bp->advertising = (ADVERTISED_100baseT_Full |
-                                          ADVERTISED_TP);
+                       bp->port.advertising = (ADVERTISED_100baseT_Full |
+                                               ADVERTISED_TP);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
                break;
 
        case PORT_FEATURE_LINK_SPEED_100M_HALF:
-               if (bp->supported & SUPPORTED_100baseT_Half) {
+               if (bp->port.supported & SUPPORTED_100baseT_Half) {
                        bp->link_params.req_line_speed = SPEED_100;
                        bp->link_params.req_duplex = DUPLEX_HALF;
-                       bp->advertising = (ADVERTISED_100baseT_Half |
-                                          ADVERTISED_TP);
+                       bp->port.advertising = (ADVERTISED_100baseT_Half |
+                                               ADVERTISED_TP);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
                break;
 
        case PORT_FEATURE_LINK_SPEED_1G:
-               if (bp->supported & SUPPORTED_1000baseT_Full) {
+               if (bp->port.supported & SUPPORTED_1000baseT_Full) {
                        bp->link_params.req_line_speed = SPEED_1000;
-                       bp->advertising = (ADVERTISED_1000baseT_Full |
-                                          ADVERTISED_TP);
+                       bp->port.advertising = (ADVERTISED_1000baseT_Full |
+                                               ADVERTISED_TP);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
                break;
 
        case PORT_FEATURE_LINK_SPEED_2_5G:
-               if (bp->supported & SUPPORTED_2500baseX_Full) {
+               if (bp->port.supported & SUPPORTED_2500baseX_Full) {
                        bp->link_params.req_line_speed = SPEED_2500;
-                       bp->advertising = (ADVERTISED_2500baseX_Full |
-                                          ADVERTISED_TP);
+                       bp->port.advertising = (ADVERTISED_2500baseX_Full |
+                                               ADVERTISED_TP);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
@@ -5337,15 +6212,15 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
        case PORT_FEATURE_LINK_SPEED_10G_CX4:
        case PORT_FEATURE_LINK_SPEED_10G_KX4:
        case PORT_FEATURE_LINK_SPEED_10G_KR:
-               if (bp->supported & SUPPORTED_10000baseT_Full) {
+               if (bp->port.supported & SUPPORTED_10000baseT_Full) {
                        bp->link_params.req_line_speed = SPEED_10000;
-                       bp->advertising = (ADVERTISED_10000baseT_Full |
-                                          ADVERTISED_FIBRE);
+                       bp->port.advertising = (ADVERTISED_10000baseT_Full |
+                                               ADVERTISED_FIBRE);
                } else {
                        BNX2X_ERR("NVRAM config error. "
                                  "Invalid link_config 0x%x"
                                  "  speed_cap_mask 0x%x\n",
-                                 bp->link_config,
+                                 bp->port.link_config,
                                  bp->link_params.speed_cap_mask);
                        return;
                }
@@ -5354,64 +6229,33 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
        default:
                BNX2X_ERR("NVRAM config error. "
                          "BAD link speed link_config 0x%x\n",
-                         bp->link_config);
+                         bp->port.link_config);
                bp->link_params.req_line_speed = SPEED_AUTO_NEG;
-               bp->advertising = bp->supported;
+               bp->port.advertising = bp->port.supported;
                break;
        }
 
-       bp->link_params.req_flow_ctrl = (bp->link_config &
-                            PORT_FEATURE_FLOW_CONTROL_MASK);
+       bp->link_params.req_flow_ctrl = (bp->port.link_config &
+                                        PORT_FEATURE_FLOW_CONTROL_MASK);
        if ((bp->link_params.req_flow_ctrl == FLOW_CTRL_AUTO) &&
-           (!bp->supported & SUPPORTED_Autoneg))
+           (!bp->port.supported & SUPPORTED_Autoneg))
                bp->link_params.req_flow_ctrl = FLOW_CTRL_NONE;
 
        BNX2X_DEV_INFO("req_line_speed %d  req_duplex %d  req_flow_ctrl 0x%x"
                       "  advertising 0x%x\n",
                       bp->link_params.req_line_speed,
                       bp->link_params.req_duplex,
-                      bp->link_params.req_flow_ctrl, bp->advertising);
+                      bp->link_params.req_flow_ctrl, bp->port.advertising);
 }
 
-static void bnx2x_get_hwinfo(struct bnx2x *bp)
+static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 {
-       u32 val, val2, val3, val4, id;
-       int port = bp->port;
-
-       bp->shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
-       BNX2X_DEV_INFO("shmem offset is %x\n", bp->shmem_base);
-
-       /* Get the chip revision id and number. */
-       /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
-       val = REG_RD(bp, MISC_REG_CHIP_NUM);
-       id = ((val & 0xffff) << 16);
-       val = REG_RD(bp, MISC_REG_CHIP_REV);
-       id |= ((val & 0xf) << 12);
-       val = REG_RD(bp, MISC_REG_CHIP_METAL);
-       id |= ((val & 0xff) << 4);
-       REG_RD(bp, MISC_REG_BOND_ID);
-       id |= (val & 0xf);
-       bp->chip_id = id;
-       BNX2X_DEV_INFO("chip ID is %x\n", id);
+       int port = BP_PORT(bp);
+       u32 val, val2;
 
        bp->link_params.bp = bp;
+       bp->link_params.port = port;
 
-       if (!bp->shmem_base || (bp->shmem_base != 0xAF900)) {
-               BNX2X_DEV_INFO("MCP not active\n");
-               nomcp = 1;
-               goto set_mac;
-       }
-
-       val = SHMEM_RD(bp, validity_map[port]);
-       if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-               != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-               BNX2X_ERR("BAD MCP validity signature\n");
-
-       bp->fw_seq = (SHMEM_RD(bp, func_mb[port].drv_mb_header) &
-                     DRV_MSG_SEQ_NUMBER_MASK);
-
-       bp->hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
-       bp->board = SHMEM_RD(bp, dev_info.shared_hw_config.board);
        bp->link_params.serdes_config =
                SHMEM_RD(bp, dev_info.port_hw_config[port].serdes_config);
        bp->link_params.lane_config =
@@ -5423,19 +6267,18 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp)
                SHMEM_RD(bp,
                         dev_info.port_hw_config[port].speed_capability_mask);
 
-       bp->link_config =
+       bp->port.link_config =
                SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
 
-       BNX2X_DEV_INFO("serdes_config (%08x)  lane_config (%08x)\n"
-            KERN_INFO "  ext_phy_config (%08x)  speed_cap_mask (%08x)"
-                      "  link_config (%08x)\n",
+       BNX2X_DEV_INFO("serdes_config 0x%08x  lane_config 0x%08x\n"
+            KERN_INFO "  ext_phy_config 0x%08x  speed_cap_mask 0x%08x"
+                      "  link_config 0x%08x\n",
                       bp->link_params.serdes_config,
                       bp->link_params.lane_config,
                       bp->link_params.ext_phy_config,
-                      bp->link_params.speed_cap_mask,
-                      bp->link_config);
+                      bp->link_params.speed_cap_mask, bp->port.link_config);
 
-       bp->link_params.switch_cfg = (bp->link_config &
+       bp->link_params.switch_cfg = (bp->port.link_config &
                                      PORT_FEATURE_CONNECTED_SWITCH_MASK);
        bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
 
@@ -5451,43 +6294,126 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp)
        bp->dev->dev_addr[5] = (u8)(val & 0xff);
        memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
        memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
+}
+
+static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
+{
+       int func = BP_FUNC(bp);
+       u32 val, val2;
+       int rc = 0;
 
+       bnx2x_get_common_hwinfo(bp);
 
+       bp->e1hov = 0;
+       bp->e1hmf = 0;
+       if (CHIP_IS_E1H(bp)) {
+               bp->mf_config =
+                       SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
 
-       val = SHMEM_RD(bp, dev_info.shared_hw_config.part_num);
-       val2 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[4]);
-       val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]);
-       val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]);
+               val =
+                  (SHMEM_RD(bp, mf_cfg.func_mf_config[func].e1hov_tag) &
+                   FUNC_MF_CFG_E1HOV_TAG_MASK);
+               if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
 
-       printk(KERN_INFO PFX "part number %X-%X-%X-%X\n",
-              val, val2, val3, val4);
+                       bp->e1hov = val;
+                       bp->e1hmf = 1;
+                       BNX2X_DEV_INFO("MF mode  E1HOV for func %d is %d "
+                                      "(0x%04x)\n",
+                                      func, bp->e1hov, bp->e1hov);
+               } else {
+                       BNX2X_DEV_INFO("Single function mode\n");
+                       if (BP_E1HVN(bp)) {
+                               BNX2X_ERR("!!!  No valid E1HOV for func %d,"
+                                         "  aborting\n", func);
+                               rc = -EPERM;
+                       }
+               }
+       }
 
-       /* bc ver */
-       if (!nomcp) {
-               bp->bc_ver = val = ((SHMEM_RD(bp, dev_info.bc_rev)) >> 8);
-               BNX2X_DEV_INFO("bc_ver %X\n", val);
-               if (val < BNX2X_BC_VER) {
-                       /* for now only warn
-                        * later we might need to enforce this */
-                       BNX2X_ERR("This driver needs bc_ver %X but found %X,"
-                                 " please upgrade BC\n", BNX2X_BC_VER, val);
+       if (!BP_NOMCP(bp)) {
+               bnx2x_get_port_hwinfo(bp);
+
+               bp->fw_seq = (SHMEM_RD(bp, func_mb[func].drv_mb_header) &
+                             DRV_MSG_SEQ_NUMBER_MASK);
+               BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
+       }
+
+       if (IS_E1HMF(bp)) {
+               val2 = SHMEM_RD(bp, mf_cfg.func_mf_config[func].mac_upper);
+               val = SHMEM_RD(bp,  mf_cfg.func_mf_config[func].mac_lower);
+               if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
+                   (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) {
+                       bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
+                       bp->dev->dev_addr[1] = (u8)(val2 & 0xff);
+                       bp->dev->dev_addr[2] = (u8)(val >> 24 & 0xff);
+                       bp->dev->dev_addr[3] = (u8)(val >> 16 & 0xff);
+                       bp->dev->dev_addr[4] = (u8)(val >> 8  & 0xff);
+                       bp->dev->dev_addr[5] = (u8)(val & 0xff);
+                       memcpy(bp->link_params.mac_addr, bp->dev->dev_addr,
+                              ETH_ALEN);
+                       memcpy(bp->dev->perm_addr, bp->dev->dev_addr,
+                              ETH_ALEN);
                }
-       } else {
-               bp->bc_ver = 0;
+
+               return rc;
        }
 
-       val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
-       bp->flash_size = (NVRAM_1MB_SIZE << (val & MCPR_NVM_CFG4_FLASH_SIZE));
-       BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
-                      bp->flash_size, bp->flash_size);
+       if (BP_NOMCP(bp)) {
+               /* only supposed to happen on emulation/FPGA */
+               BNX2X_ERR("warning rendom MAC workaround active\n");
+               random_ether_addr(bp->dev->dev_addr);
+               memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
+       }
 
-       return;
+       return rc;
+}
+
+static int __devinit bnx2x_init_bp(struct bnx2x *bp)
+{
+       int func = BP_FUNC(bp);
+       int rc;
+
+       if (nomcp)
+               bp->flags |= NO_MCP_FLAG;
 
-set_mac: /* only supposed to happen on emulation/FPGA */
-       BNX2X_ERR("warning rendom MAC workaround active\n");
-       random_ether_addr(bp->dev->dev_addr);
-       memcpy(bp->dev->perm_addr, bp->dev->dev_addr, 6);
+       mutex_init(&bp->port.phy_mutex);
 
+       INIT_WORK(&bp->sp_task, bnx2x_sp_task);
+       INIT_WORK(&bp->reset_task, bnx2x_reset_task);
+
+       rc = bnx2x_get_hwinfo(bp);
+
+       /* need to reset chip if undi was active */
+       if (!BP_NOMCP(bp))
+               bnx2x_undi_unload(bp);
+
+       if (CHIP_REV_IS_FPGA(bp))
+               printk(KERN_ERR PFX "FPGA detected\n");
+
+       if (BP_NOMCP(bp) && (func == 0))
+               printk(KERN_ERR PFX
+                      "MCP disabled, must load devices in order!\n");
+
+       bp->tx_ring_size = MAX_TX_AVAIL;
+       bp->rx_ring_size = MAX_RX_AVAIL;
+
+       bp->rx_csum = 1;
+       bp->rx_offset = 0;
+
+       bp->tx_ticks = 50;
+       bp->rx_ticks = 25;
+
+       bp->stats_ticks = 1000000 & 0xffff00;
+
+       bp->timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
+       bp->current_interval = (poll ? poll : bp->timer_interval);
+
+       init_timer(&bp->timer);
+       bp->timer.expires = jiffies + bp->current_interval;
+       bp->timer.data = (unsigned long) bp;
+       bp->timer.function = bnx2x_timer;
+
+       return rc;
 }
 
 /*
@@ -5500,8 +6426,8 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-       cmd->supported = bp->supported;
-       cmd->advertising = bp->advertising;
+       cmd->supported = bp->port.supported;
+       cmd->advertising = bp->port.advertising;
 
        if (netif_carrier_ok(dev)) {
                cmd->speed = bp->link_vars.line_speed;
@@ -5510,6 +6436,14 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->speed = bp->link_params.req_line_speed;
                cmd->duplex = bp->link_params.req_duplex;
        }
+       if (IS_E1HMF(bp)) {
+               u16 vn_max_rate;
+
+               vn_max_rate = ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
+                               FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+               if (vn_max_rate < cmd->speed)
+                       cmd->speed = vn_max_rate;
+       }
 
        if (bp->link_params.switch_cfg == SWITCH_CFG_10G) {
                u32 ext_phy_type =
@@ -5541,7 +6475,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        } else
                cmd->port = PORT_TP;
 
-       cmd->phy_address = bp->phy_addr;
+       cmd->phy_address = bp->port.phy_addr;
        cmd->transceiver = XCVR_INTERNAL;
 
        if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
@@ -5568,6 +6502,9 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        struct bnx2x *bp = netdev_priv(dev);
        u32 advertising;
 
+       if (IS_E1HMF(bp))
+               return 0;
+
        DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
           DP_LEVEL "  supported 0x%x  advertising 0x%x  speed %d\n"
           DP_LEVEL "  duplex %d  port %d  phy_address %d  transceiver %d\n"
@@ -5577,24 +6514,25 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
           cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
 
        if (cmd->autoneg == AUTONEG_ENABLE) {
-               if (!(bp->supported & SUPPORTED_Autoneg)) {
-                       DP(NETIF_MSG_LINK, "Aotoneg not supported\n");
+               if (!(bp->port.supported & SUPPORTED_Autoneg)) {
+                       DP(NETIF_MSG_LINK, "Autoneg not supported\n");
                        return -EINVAL;
                }
 
                /* advertise the requested speed and duplex if supported */
-               cmd->advertising &= bp->supported;
+               cmd->advertising &= bp->port.supported;
 
                bp->link_params.req_line_speed = SPEED_AUTO_NEG;
                bp->link_params.req_duplex = DUPLEX_FULL;
-               bp->advertising |= (ADVERTISED_Autoneg | cmd->advertising);
+               bp->port.advertising |= (ADVERTISED_Autoneg |
+                                        cmd->advertising);
 
        } else { /* forced speed */
                /* advertise the requested speed and duplex if supported */
                switch (cmd->speed) {
                case SPEED_10:
                        if (cmd->duplex == DUPLEX_FULL) {
-                               if (!(bp->supported &
+                               if (!(bp->port.supported &
                                      SUPPORTED_10baseT_Full)) {
                                        DP(NETIF_MSG_LINK,
                                           "10M full not supported\n");
@@ -5604,7 +6542,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                advertising = (ADVERTISED_10baseT_Full |
                                               ADVERTISED_TP);
                        } else {
-                               if (!(bp->supported &
+                               if (!(bp->port.supported &
                                      SUPPORTED_10baseT_Half)) {
                                        DP(NETIF_MSG_LINK,
                                           "10M half not supported\n");
@@ -5618,7 +6556,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
                case SPEED_100:
                        if (cmd->duplex == DUPLEX_FULL) {
-                               if (!(bp->supported &
+                               if (!(bp->port.supported &
                                                SUPPORTED_100baseT_Full)) {
                                        DP(NETIF_MSG_LINK,
                                           "100M full not supported\n");
@@ -5628,7 +6566,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                advertising = (ADVERTISED_100baseT_Full |
                                               ADVERTISED_TP);
                        } else {
-                               if (!(bp->supported &
+                               if (!(bp->port.supported &
                                                SUPPORTED_100baseT_Half)) {
                                        DP(NETIF_MSG_LINK,
                                           "100M half not supported\n");
@@ -5646,7 +6584,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                return -EINVAL;
                        }
 
-                       if (!(bp->supported & SUPPORTED_1000baseT_Full)) {
+                       if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) {
                                DP(NETIF_MSG_LINK, "1G full not supported\n");
                                return -EINVAL;
                        }
@@ -5662,7 +6600,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                return -EINVAL;
                        }
 
-                       if (!(bp->supported & SUPPORTED_2500baseX_Full)) {
+                       if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) {
                                DP(NETIF_MSG_LINK,
                                   "2.5G full not supported\n");
                                return -EINVAL;
@@ -5678,7 +6616,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                return -EINVAL;
                        }
 
-                       if (!(bp->supported & SUPPORTED_10000baseT_Full)) {
+                       if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) {
                                DP(NETIF_MSG_LINK, "10G full not supported\n");
                                return -EINVAL;
                        }
@@ -5694,16 +6632,18 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
                bp->link_params.req_line_speed = cmd->speed;
                bp->link_params.req_duplex = cmd->duplex;
-               bp->advertising = advertising;
+               bp->port.advertising = advertising;
        }
 
        DP(NETIF_MSG_LINK, "req_line_speed %d\n"
           DP_LEVEL "  req_duplex %d  advertising 0x%x\n",
           bp->link_params.req_line_speed, bp->link_params.req_duplex,
-          bp->advertising);
+          bp->port.advertising);
 
-       bnx2x_stop_stats(bp);
-       bnx2x_link_set(bp);
+       if (netif_running(dev)) {
+               bnx2x_stop_stats(bp);
+               bnx2x_link_set(bp);
+       }
 
        return 0;
 }
@@ -5720,21 +6660,23 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
        strcpy(info->version, DRV_MODULE_VERSION);
 
        phy_fw_ver[0] = '\0';
-       bnx2x_phy_hw_lock(bp);
-       bnx2x_get_ext_phy_fw_version(&bp->link_params,
-                                    (bp->state != BNX2X_STATE_CLOSED),
-                                    phy_fw_ver, PHY_FW_VER_LEN);
-       bnx2x_phy_hw_unlock(bp);
+       if (bp->port.pmf) {
+               bnx2x_phy_hw_lock(bp);
+               bnx2x_get_ext_phy_fw_version(&bp->link_params,
+                                            (bp->state != BNX2X_STATE_CLOSED),
+                                            phy_fw_ver, PHY_FW_VER_LEN);
+               bnx2x_phy_hw_unlock(bp);
+       }
 
        snprintf(info->fw_version, 32, "%d.%d.%d:%d BC:%x%s%s",
                 BCM_5710_FW_MAJOR_VERSION, BCM_5710_FW_MINOR_VERSION,
                 BCM_5710_FW_REVISION_VERSION,
-                BCM_5710_FW_COMPILE_FLAGS, bp->bc_ver,
+                BCM_5710_FW_COMPILE_FLAGS, bp->common.bc_ver,
                 ((phy_fw_ver[0] != '\0')? " PHY:":""), phy_fw_ver);
        strcpy(info->bus_info, pci_name(bp->pdev));
        info->n_stats = BNX2X_NUM_STATS;
        info->testinfo_len = BNX2X_NUM_TESTS;
-       info->eedump_len = bp->flash_size;
+       info->eedump_len = bp->common.flash_size;
        info->regdump_len = 0;
 }
 
@@ -5767,9 +6709,9 @@ static int bnx2x_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
                        return -EINVAL;
 
                bp->wol = 1;
-       } else {
+       } else
                bp->wol = 0;
-       }
+
        return 0;
 }
 
@@ -5792,13 +6734,13 @@ static int bnx2x_nway_reset(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-       if (bp->state != BNX2X_STATE_OPEN) {
-               DP(NETIF_MSG_PROBE, "state is %x, returning\n", bp->state);
-               return -EAGAIN;
-       }
+       if (!bp->port.pmf)
+               return 0;
 
-       bnx2x_stop_stats(bp);
-       bnx2x_link_set(bp);
+       if (netif_running(dev)) {
+               bnx2x_stop_stats(bp);
+               bnx2x_link_set(bp);
+       }
 
        return 0;
 }
@@ -5807,12 +6749,12 @@ static int bnx2x_get_eeprom_len(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-       return bp->flash_size;
+       return bp->common.flash_size;
 }
 
 static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int count, i;
        u32 val = 0;
 
@@ -5834,7 +6776,7 @@ static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
        }
 
        if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) {
-               DP(NETIF_MSG_NVM, "cannot get access to nvram interface\n");
+               DP(BNX2X_MSG_NVM, "cannot get access to nvram interface\n");
                return -EBUSY;
        }
 
@@ -5843,7 +6785,7 @@ static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
 
 static int bnx2x_release_nvram_lock(struct bnx2x *bp)
 {
-       int port = bp->port;
+       int port = BP_PORT(bp);
        int count, i;
        u32 val = 0;
 
@@ -5865,7 +6807,7 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp)
        }
 
        if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) {
-               DP(NETIF_MSG_NVM, "cannot free access to nvram interface\n");
+               DP(BNX2X_MSG_NVM, "cannot free access to nvram interface\n");
                return -EBUSY;
        }
 
@@ -5929,7 +6871,6 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, u32 *ret_val,
 
                if (val & MCPR_NVM_COMMAND_DONE) {
                        val = REG_RD(bp, MCP_REG_MCPR_NVM_READ);
-                       DP(NETIF_MSG_NVM, "val 0x%08x\n", val);
                        /* we read nvram data in cpu order
                         * but ethtool sees it as an array of bytes
                         * converting to big-endian will do the work */
@@ -5951,16 +6892,16 @@ static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
        u32 val;
 
        if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
-               DP(NETIF_MSG_NVM,
+               DP(BNX2X_MSG_NVM,
                   "Invalid parameter: offset 0x%x  buf_size 0x%x\n",
                   offset, buf_size);
                return -EINVAL;
        }
 
-       if (offset + buf_size > bp->flash_size) {
-               DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
+       if (offset + buf_size > bp->common.flash_size) {
+               DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
                                  " buf_size (0x%x) > flash_size (0x%x)\n",
-                  offset, buf_size, bp->flash_size);
+                  offset, buf_size, bp->common.flash_size);
                return -EINVAL;
        }
 
@@ -6004,7 +6945,7 @@ static int bnx2x_get_eeprom(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
        int rc;
 
-       DP(NETIF_MSG_NVM, "ethtool_eeprom: cmd %d\n"
+       DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
           DP_LEVEL "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
           eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
           eeprom->len, eeprom->len);
@@ -6066,10 +7007,10 @@ static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
        u32 align_offset;
        u32 val;
 
-       if (offset + buf_size > bp->flash_size) {
-               DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
+       if (offset + buf_size > bp->common.flash_size) {
+               DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
                                  " buf_size (0x%x) > flash_size (0x%x)\n",
-                  offset, buf_size, bp->flash_size);
+                  offset, buf_size, bp->common.flash_size);
                return -EINVAL;
        }
 
@@ -6093,8 +7034,6 @@ static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
                 * convert it back to cpu order */
                val = be32_to_cpu(val);
 
-               DP(NETIF_MSG_NVM, "val 0x%08x\n", val);
-
                rc = bnx2x_nvram_write_dword(bp, align_offset, val,
                                             cmd_flags);
        }
@@ -6114,21 +7053,20 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
        u32 val;
        u32 written_so_far;
 
-       if (buf_size == 1) {    /* ethtool */
+       if (buf_size == 1)      /* ethtool */
                return bnx2x_nvram_write1(bp, offset, data_buf, buf_size);
-       }
 
        if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
-               DP(NETIF_MSG_NVM,
+               DP(BNX2X_MSG_NVM,
                   "Invalid parameter: offset 0x%x  buf_size 0x%x\n",
                   offset, buf_size);
                return -EINVAL;
        }
 
-       if (offset + buf_size > bp->flash_size) {
-               DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
+       if (offset + buf_size > bp->common.flash_size) {
+               DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
                                  " buf_size (0x%x) > flash_size (0x%x)\n",
-                  offset, buf_size, bp->flash_size);
+                  offset, buf_size, bp->common.flash_size);
                return -EINVAL;
        }
 
@@ -6151,7 +7089,6 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
                        cmd_flags |= MCPR_NVM_COMMAND_FIRST;
 
                memcpy(&val, data_buf, 4);
-               DP(NETIF_MSG_NVM, "val 0x%08x\n", val);
 
                rc = bnx2x_nvram_write_dword(bp, offset, val, cmd_flags);
 
@@ -6175,7 +7112,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
        int rc;
 
-       DP(NETIF_MSG_NVM, "ethtool_eeprom: cmd %d\n"
+       DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
           DP_LEVEL "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
           eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
           eeprom->len, eeprom->len);
@@ -6183,20 +7120,23 @@ static int bnx2x_set_eeprom(struct net_device *dev,
        /* parameters already validated in ethtool_set_eeprom */
 
        /* If the magic number is PHY (0x00504859) upgrade the PHY FW */
-       if (eeprom->magic == 0x00504859) {
-
-               bnx2x_phy_hw_lock(bp);
-               rc = bnx2x_flash_download(bp, bp->port,
-                                    bp->link_params.ext_phy_config,
-                                    (bp->state != BNX2X_STATE_CLOSED),
-                                    eebuf, eeprom->len);
-               rc |= bnx2x_link_reset(&bp->link_params,
-                                      &bp->link_vars);
-               rc |= bnx2x_phy_init(&bp->link_params,
-                                    &bp->link_vars);
-               bnx2x_phy_hw_unlock(bp);
-
-       } else
+       if (eeprom->magic == 0x00504859)
+               if (bp->port.pmf) {
+
+                       bnx2x_phy_hw_lock(bp);
+                       rc = bnx2x_flash_download(bp, BP_PORT(bp),
+                                            bp->link_params.ext_phy_config,
+                                            (bp->state != BNX2X_STATE_CLOSED),
+                                            eebuf, eeprom->len);
+                               rc |= bnx2x_link_reset(&bp->link_params,
+                                                      &bp->link_vars);
+                               rc |= bnx2x_phy_init(&bp->link_params,
+                                                    &bp->link_vars);
+                       bnx2x_phy_hw_unlock(bp);
+
+               } else /* Only the PMF can access the PHY */
+                       return -EINVAL;
+       else
                rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
 
        return rc;
@@ -6234,7 +7174,7 @@ static int bnx2x_set_coalesce(struct net_device *dev,
                bp->stats_ticks = 0xffff00;
        bp->stats_ticks &= 0xffff00;
 
-       if (netif_running(bp->dev))
+       if (netif_running(dev))
                bnx2x_update_coalesce(bp);
 
        return 0;
@@ -6261,6 +7201,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
                               struct ethtool_ringparam *ering)
 {
        struct bnx2x *bp = netdev_priv(dev);
+       int rc = 0;
 
        if ((ering->rx_pending > MAX_RX_AVAIL) ||
            (ering->tx_pending > MAX_TX_AVAIL) ||
@@ -6270,12 +7211,12 @@ static int bnx2x_set_ringparam(struct net_device *dev,
        bp->rx_ring_size = ering->rx_pending;
        bp->tx_ring_size = ering->tx_pending;
 
-       if (netif_running(bp->dev)) {
-               bnx2x_nic_unload(bp, 0);
-               bnx2x_nic_load(bp, 0);
+       if (netif_running(dev)) {
+               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+               rc = bnx2x_nic_load(bp, LOAD_NORMAL);
        }
 
-       return 0;
+       return rc;
 }
 
 static void bnx2x_get_pauseparam(struct net_device *dev,
@@ -6301,6 +7242,9 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
 {
        struct bnx2x *bp = netdev_priv(dev);
 
+       if (IS_E1HMF(bp))
+               return 0;
+
        DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
           DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
           epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
@@ -6317,7 +7261,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
                bp->link_params.req_flow_ctrl = FLOW_CTRL_NONE;
 
        if (epause->autoneg) {
-               if (!(bp->supported & SUPPORTED_Autoneg)) {
+               if (!(bp->port.supported & SUPPORTED_Autoneg)) {
                        DP(NETIF_MSG_LINK, "Autoneg not supported\n");
                        return -EINVAL;
                }
@@ -6328,8 +7272,11 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
 
        DP(NETIF_MSG_LINK,
           "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl);
-       bnx2x_stop_stats(bp);
-       bnx2x_link_set(bp);
+
+       if (netif_running(dev)) {
+               bnx2x_stop_stats(bp);
+               bnx2x_link_set(bp);
+       }
 
        return 0;
 }
@@ -6531,18 +7478,25 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
 static int bnx2x_phys_id(struct net_device *dev, u32 data)
 {
        struct bnx2x *bp = netdev_priv(dev);
+       int port = BP_PORT(bp);
        int i;
 
+       if (!netif_running(dev))
+               return 0;
+
+       if (!bp->port.pmf)
+               return 0;
+
        if (data == 0)
                data = 2;
 
        for (i = 0; i < (data * 2); i++) {
                if ((i % 2) == 0)
-                       bnx2x_set_led(bp, bp->port, LED_MODE_OPER, SPEED_1000,
+                       bnx2x_set_led(bp, port, LED_MODE_OPER, SPEED_1000,
                                      bp->link_params.hw_led_mode,
                                      bp->link_params.chip_id);
                else
-                       bnx2x_set_led(bp, bp->port, LED_MODE_OFF, 0,
+                       bnx2x_set_led(bp, port, LED_MODE_OFF, 0,
                                      bp->link_params.hw_led_mode,
                                      bp->link_params.chip_id);
 
@@ -6552,7 +7506,7 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
        }
 
        if (bp->link_vars.link_up)
-               bnx2x_set_led(bp, bp->port, LED_MODE_OPER,
+               bnx2x_set_led(bp, port, LED_MODE_OPER,
                              bp->link_vars.line_speed,
                              bp->link_params.hw_led_mode,
                              bp->link_params.chip_id);
@@ -6609,117 +7563,40 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
 
        switch (state) {
        case PCI_D0:
-               pci_write_config_word(bp->pdev,
-                                     bp->pm_cap + PCI_PM_CTRL,
+               pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
                                      ((pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
                                       PCI_PM_CTRL_PME_STATUS));
 
                if (pmcsr & PCI_PM_CTRL_STATE_MASK)
                /* delay required during transition out of D3hot */
                        msleep(20);
-               break;
-
-       case PCI_D3hot:
-               pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-               pmcsr |= 3;
-
-               if (bp->wol)
-                       pmcsr |= PCI_PM_CTRL_PME_ENABLE;
-
-               pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-                                     pmcsr);
-
-               /* No more memory access after this point until
-               * device is brought back to D0.
-               */
-               break;
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/*
- * net_device service functions
- */
-
-/* called with netif_tx_lock from set_multicast */
-static void bnx2x_set_rx_mode(struct net_device *dev)
-{
-       struct bnx2x *bp = netdev_priv(dev);
-       u32 rx_mode = BNX2X_RX_MODE_NORMAL;
-
-       DP(NETIF_MSG_IFUP, "called dev->flags = %x\n", dev->flags);
-
-       if (dev->flags & IFF_PROMISC)
-               rx_mode = BNX2X_RX_MODE_PROMISC;
-
-       else if ((dev->flags & IFF_ALLMULTI) ||
-                (dev->mc_count > BNX2X_MAX_MULTICAST))
-               rx_mode = BNX2X_RX_MODE_ALLMULTI;
-
-       else { /* some multicasts */
-               int i, old, offset;
-               struct dev_mc_list *mclist;
-               struct mac_configuration_cmd *config =
-                                               bnx2x_sp(bp, mcast_config);
-
-               for (i = 0, mclist = dev->mc_list;
-                    mclist && (i < dev->mc_count);
-                    i++, mclist = mclist->next) {
-
-                       config->config_table[i].cam_entry.msb_mac_addr =
-                                       swab16(*(u16 *)&mclist->dmi_addr[0]);
-                       config->config_table[i].cam_entry.middle_mac_addr =
-                                       swab16(*(u16 *)&mclist->dmi_addr[2]);
-                       config->config_table[i].cam_entry.lsb_mac_addr =
-                                       swab16(*(u16 *)&mclist->dmi_addr[4]);
-                       config->config_table[i].cam_entry.flags =
-                                                       cpu_to_le16(bp->port);
-                       config->config_table[i].target_table_entry.flags = 0;
-                       config->config_table[i].target_table_entry.
-                                                               client_id = 0;
-                       config->config_table[i].target_table_entry.
-                                                               vlan_id = 0;
-
-                       DP(NETIF_MSG_IFUP,
-                          "setting MCAST[%d] (%04x:%04x:%04x)\n",
-                          i, config->config_table[i].cam_entry.msb_mac_addr,
-                          config->config_table[i].cam_entry.middle_mac_addr,
-                          config->config_table[i].cam_entry.lsb_mac_addr);
-               }
-               old = config->hdr.length_6b;
-               if (old > i) {
-                       for (; i < old; i++) {
-                               if (CAM_IS_INVALID(config->config_table[i])) {
-                                       i--; /* already invalidated */
-                                       break;
-                               }
-                               /* invalidate */
-                               CAM_INVALIDATE(config->config_table[i]);
-                       }
-               }
+               break;
 
-               if (CHIP_REV_IS_SLOW(bp))
-                       offset = BNX2X_MAX_EMUL_MULTI*(1 + bp->port);
-               else
-                       offset = BNX2X_MAX_MULTICAST*(1 + bp->port);
+       case PCI_D3hot:
+               pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+               pmcsr |= 3;
 
-               config->hdr.length_6b = i;
-               config->hdr.offset = offset;
-               config->hdr.reserved0 = 0;
-               config->hdr.reserved1 = 0;
+               if (bp->wol)
+                       pmcsr |= PCI_PM_CTRL_PME_ENABLE;
 
-               bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
-                             U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
-                             U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
-       }
+               pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+                                     pmcsr);
 
-       bp->rx_mode = rx_mode;
-       bnx2x_set_storm_rx_mode(bp);
+               /* No more memory access after this point until
+               * device is brought back to D0.
+               */
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
 }
 
+/*
+ * net_device service functions
+ */
+
 static int bnx2x_poll(struct napi_struct *napi, int budget)
 {
        struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
@@ -6729,7 +7606,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
 
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic))
-               goto out_panic;
+               goto poll_panic;
 #endif
 
        prefetch(fp->tx_buf_ring[TX_BD(fp->tx_pkt_cons)].skb);
@@ -6738,30 +7615,28 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
 
        bnx2x_update_fpsb_idx(fp);
 
-       if (le16_to_cpu(*fp->tx_cons_sb) != fp->tx_pkt_cons)
+       if ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) ||
+           (fp->tx_pkt_prod != fp->tx_pkt_cons))
                bnx2x_tx_int(fp, budget);
 
-
        if (le16_to_cpu(*fp->rx_cons_sb) != fp->rx_comp_cons)
                work_done = bnx2x_rx_int(fp, budget);
 
-
        rmb(); /* bnx2x_has_work() reads the status block */
 
        /* must not complete if we consumed full budget */
        if ((work_done < budget) && !bnx2x_has_work(fp)) {
 
 #ifdef BNX2X_STOP_ON_ERROR
-out_panic:
+poll_panic:
 #endif
                netif_rx_complete(bp->dev, napi);
 
-               bnx2x_ack_sb(bp, fp->index, USTORM_ID,
+               bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID,
                             le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
-               bnx2x_ack_sb(bp, fp->index, CSTORM_ID,
+               bnx2x_ack_sb(bp, FP_SB_ID(fp), CSTORM_ID,
                             le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
        }
-
        return work_done;
 }
 
@@ -7055,18 +7930,145 @@ static int bnx2x_close(struct net_device *dev)
        return 0;
 }
 
-/* Called with rtnl_lock */
+/* called with netif_tx_lock from set_multicast */
+static void bnx2x_set_rx_mode(struct net_device *dev)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       u32 rx_mode = BNX2X_RX_MODE_NORMAL;
+       int port = BP_PORT(bp);
+
+       if (bp->state != BNX2X_STATE_OPEN) {
+               DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
+               return;
+       }
+
+       DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags);
+
+       if (dev->flags & IFF_PROMISC)
+               rx_mode = BNX2X_RX_MODE_PROMISC;
+
+       else if ((dev->flags & IFF_ALLMULTI) ||
+                ((dev->mc_count > BNX2X_MAX_MULTICAST) && CHIP_IS_E1(bp)))
+               rx_mode = BNX2X_RX_MODE_ALLMULTI;
+
+       else { /* some multicasts */
+               if (CHIP_IS_E1(bp)) {
+                       int i, old, offset;
+                       struct dev_mc_list *mclist;
+                       struct mac_configuration_cmd *config =
+                                               bnx2x_sp(bp, mcast_config);
+
+                       for (i = 0, mclist = dev->mc_list;
+                            mclist && (i < dev->mc_count);
+                            i++, mclist = mclist->next) {
+
+                               config->config_table[i].
+                                       cam_entry.msb_mac_addr =
+                                       swab16(*(u16 *)&mclist->dmi_addr[0]);
+                               config->config_table[i].
+                                       cam_entry.middle_mac_addr =
+                                       swab16(*(u16 *)&mclist->dmi_addr[2]);
+                               config->config_table[i].
+                                       cam_entry.lsb_mac_addr =
+                                       swab16(*(u16 *)&mclist->dmi_addr[4]);
+                               config->config_table[i].cam_entry.flags =
+                                                       cpu_to_le16(port);
+                               config->config_table[i].
+                                       target_table_entry.flags = 0;
+                               config->config_table[i].
+                                       target_table_entry.client_id = 0;
+                               config->config_table[i].
+                                       target_table_entry.vlan_id = 0;
+
+                               DP(NETIF_MSG_IFUP,
+                                  "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
+                                  config->config_table[i].
+                                               cam_entry.msb_mac_addr,
+                                  config->config_table[i].
+                                               cam_entry.middle_mac_addr,
+                                  config->config_table[i].
+                                               cam_entry.lsb_mac_addr);
+                       }
+                       old = config->hdr.length_6b;
+                       if (old > i) {
+                               for (; i < old; i++) {
+                                       if (CAM_IS_INVALID(config->
+                                                          config_table[i])) {
+                                               i--; /* already invalidated */
+                                               break;
+                                       }
+                                       /* invalidate */
+                                       CAM_INVALIDATE(config->
+                                                      config_table[i]);
+                               }
+                       }
+
+                       if (CHIP_REV_IS_SLOW(bp))
+                               offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
+                       else
+                               offset = BNX2X_MAX_MULTICAST*(1 + port);
+
+                       config->hdr.length_6b = i;
+                       config->hdr.offset = offset;
+                       config->hdr.client_id = BP_CL_ID(bp);
+                       config->hdr.reserved1 = 0;
+
+                       bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+                                  U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
+                                  U64_LO(bnx2x_sp_mapping(bp, mcast_config)),
+                                     0);
+               } else { /* E1H */
+                       /* Accept one or more multicasts */
+                       struct dev_mc_list *mclist;
+                       u32 mc_filter[MC_HASH_SIZE];
+                       u32 crc, bit, regidx;
+                       int i;
+
+                       memset(mc_filter, 0, 4 * MC_HASH_SIZE);
+
+                       for (i = 0, mclist = dev->mc_list;
+                            mclist && (i < dev->mc_count);
+                            i++, mclist = mclist->next) {
+
+                               DP(NETIF_MSG_IFUP, "Adding mcast MAC: "
+                                  "%02x:%02x:%02x:%02x:%02x:%02x\n",
+                                  mclist->dmi_addr[0], mclist->dmi_addr[1],
+                                  mclist->dmi_addr[2], mclist->dmi_addr[3],
+                                  mclist->dmi_addr[4], mclist->dmi_addr[5]);
+
+                               crc = crc32c_le(0, mclist->dmi_addr, ETH_ALEN);
+                               bit = (crc >> 24) & 0xff;
+                               regidx = bit >> 5;
+                               bit &= 0x1f;
+                               mc_filter[regidx] |= (1 << bit);
+                       }
+
+                       for (i = 0; i < MC_HASH_SIZE; i++)
+                               REG_WR(bp, MC_HASH_OFFSET(bp, i),
+                                      mc_filter[i]);
+               }
+       }
+
+       bp->rx_mode = rx_mode;
+       bnx2x_set_storm_rx_mode(bp);
+}
+
+/* called with rtnl_lock */
 static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
 {
        struct sockaddr *addr = p;
        struct bnx2x *bp = netdev_priv(dev);
 
-       if (!is_valid_ether_addr(addr->sa_data))
+       if (!is_valid_ether_addr((u8 *)(addr->sa_data)))
                return -EINVAL;
 
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-       if (netif_running(dev))
-               bnx2x_set_mac_addr(bp);
+       if (netif_running(dev)) {
+               if (CHIP_IS_E1(bp))
+                       bnx2x_set_mac_addr_e1(bp);
+               else
+                       bnx2x_set_mac_addr_e1h(bp);
+       }
 
        return 0;
 }
@@ -7080,7 +8082,7 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
        switch (cmd) {
        case SIOCGMIIPHY:
-               data->phy_id = bp->phy_addr;
+               data->phy_id = bp->port.phy_addr;
 
                /* fallthrough */
 
@@ -7090,12 +8092,12 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (!netif_running(dev))
                        return -EAGAIN;
 
-               mutex_lock(&bp->phy_mutex);
-               err = bnx2x_cl45_read(bp, bp->port, 0, bp->phy_addr,
+               mutex_lock(&bp->port.phy_mutex);
+               err = bnx2x_cl45_read(bp, BP_PORT(bp), 0, bp->port.phy_addr,
                                      DEFAULT_PHY_DEV_ADDR,
                                      (data->reg_num & 0x1f), &mii_regval);
                data->val_out = mii_regval;
-               mutex_unlock(&bp->phy_mutex);
+               mutex_unlock(&bp->port.phy_mutex);
                return err;
        }
 
@@ -7106,11 +8108,11 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (!netif_running(dev))
                        return -EAGAIN;
 
-               mutex_lock(&bp->phy_mutex);
-               err = bnx2x_cl45_write(bp, bp->port, 0, bp->phy_addr,
+               mutex_lock(&bp->port.phy_mutex);
+               err = bnx2x_cl45_write(bp, BP_PORT(bp), 0, bp->port.phy_addr,
                                       DEFAULT_PHY_DEV_ADDR,
                                       (data->reg_num & 0x1f), data->val_in);
-               mutex_unlock(&bp->phy_mutex);
+               mutex_unlock(&bp->port.phy_mutex);
                return err;
 
        default:
@@ -7121,10 +8123,11 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return -EOPNOTSUPP;
 }
 
-/* Called with rtnl_lock */
+/* called with rtnl_lock */
 static int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct bnx2x *bp = netdev_priv(dev);
+       int rc = 0;
 
        if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
            ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE))
@@ -7137,10 +8140,11 @@ static int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
        dev->mtu = new_mtu;
 
        if (netif_running(dev)) {
-               bnx2x_nic_unload(bp, 0);
-               bnx2x_nic_load(bp, 0);
+               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+               rc = bnx2x_nic_load(bp, LOAD_NORMAL);
        }
-       return 0;
+
+       return rc;
 }
 
 static void bnx2x_tx_timeout(struct net_device *dev)
@@ -7156,7 +8160,7 @@ static void bnx2x_tx_timeout(struct net_device *dev)
 }
 
 #ifdef BCM_VLAN
-/* Called with rtnl_lock */
+/* called with rtnl_lock */
 static void bnx2x_vlan_rx_register(struct net_device *dev,
                                   struct vlan_group *vlgrp)
 {
@@ -7166,6 +8170,7 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
        if (netif_running(dev))
                bnx2x_set_client_config(bp);
 }
+
 #endif
 
 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
@@ -7179,36 +8184,8 @@ static void poll_bnx2x(struct net_device *dev)
 }
 #endif
 
-static void bnx2x_reset_task(struct work_struct *work)
-{
-       struct bnx2x *bp = container_of(work, struct bnx2x, reset_task);
-
-#ifdef BNX2X_STOP_ON_ERROR
-       BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
-                 " so reset not done to allow debug dump,\n"
-        KERN_ERR " you will need to reboot when done\n");
-       return;
-#endif
-
-       if (!netif_running(bp->dev))
-               return;
-
-       rtnl_lock();
-
-       if (bp->state != BNX2X_STATE_OPEN) {
-               DP(NETIF_MSG_TX_ERR, "state is %x, returning\n", bp->state);
-               goto reset_task_exit;
-       }
-
-       bnx2x_nic_unload(bp, 0);
-       bnx2x_nic_load(bp, 0);
-
-reset_task_exit:
-       rtnl_unlock();
-}
-
-static int __devinit bnx2x_init_board(struct pci_dev *pdev,
-                                     struct net_device *dev)
+static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
+                                   struct net_device *dev)
 {
        struct bnx2x *bp;
        int rc;
@@ -7216,8 +8193,10 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
        SET_NETDEV_DEV(dev, &pdev->dev);
        bp = netdev_priv(dev);
 
+       bp->dev = dev;
+       bp->pdev = pdev;
        bp->flags = 0;
-       bp->port = PCI_FUNC(pdev->devfn);
+       bp->func = PCI_FUNC(pdev->devfn);
 
        rc = pci_enable_device(pdev);
        if (rc) {
@@ -7239,14 +8218,17 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
                goto err_out_disable;
        }
 
-       rc = pci_request_regions(pdev, DRV_MODULE_NAME);
-       if (rc) {
-               printk(KERN_ERR PFX "Cannot obtain PCI resources,"
-                      " aborting\n");
-               goto err_out_disable;
-       }
+       if (atomic_read(&pdev->enable_cnt) == 1) {
+               rc = pci_request_regions(pdev, DRV_MODULE_NAME);
+               if (rc) {
+                       printk(KERN_ERR PFX "Cannot obtain PCI resources,"
+                              " aborting\n");
+                       goto err_out_disable;
+               }
 
-       pci_set_master(pdev);
+               pci_set_master(pdev);
+               pci_save_state(pdev);
+       }
 
        bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
        if (bp->pm_cap == 0) {
@@ -7280,13 +8262,9 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
                goto err_out_release;
        }
 
-       bp->dev = dev;
-       bp->pdev = pdev;
-
-       INIT_WORK(&bp->reset_task, bnx2x_reset_task);
-       INIT_WORK(&bp->sp_task, bnx2x_sp_task);
-
-       dev->base_addr = pci_resource_start(pdev, 0);
+       dev->mem_start = pci_resource_start(pdev, 0);
+       dev->base_addr = dev->mem_start;
+       dev->mem_end = pci_resource_end(pdev, 0);
 
        dev->irq = pdev->irq;
 
@@ -7298,8 +8276,9 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
                goto err_out_release;
        }
 
-       bp->doorbells = ioremap_nocache(pci_resource_start(pdev , 2),
-                                       pci_resource_len(pdev, 2));
+       bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
+                                       min_t(u64, BNX2X_DB_SIZE,
+                                             pci_resource_len(pdev, 2)));
        if (!bp->doorbells) {
                printk(KERN_ERR PFX "Cannot map doorbell space, aborting\n");
                rc = -ENOMEM;
@@ -7308,47 +8287,43 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
 
        bnx2x_set_power_state(bp, PCI_D0);
 
-       bnx2x_get_hwinfo(bp);
-
-
-       if (nomcp) {
-               printk(KERN_ERR PFX "MCP disabled, will only"
-                      " init first device\n");
-               onefunc = 1;
-       }
-
-       if (onefunc && bp->port) {
-               printk(KERN_ERR PFX "Second device disabled, exiting\n");
-               rc = -ENODEV;
-               goto err_out_unmap;
-       }
-
-       bp->tx_ring_size = MAX_TX_AVAIL;
-       bp->rx_ring_size = MAX_RX_AVAIL;
-
-       bp->rx_csum = 1;
-
-       bp->rx_offset = 0;
-
-       bp->tx_quick_cons_trip_int = 0xff;
-       bp->tx_quick_cons_trip = 0xff;
-       bp->tx_ticks_int = 50;
-       bp->tx_ticks = 50;
+       /* clean indirect addresses */
+       pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
+                              PCICFG_VENDOR_ID_OFFSET);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0 + BP_PORT(bp)*16, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0 + BP_PORT(bp)*16, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0);
+       REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0);
 
-       bp->rx_quick_cons_trip_int = 0xff;
-       bp->rx_quick_cons_trip = 0xff;
-       bp->rx_ticks_int = 25;
-       bp->rx_ticks = 25;
+       dev->hard_start_xmit = bnx2x_start_xmit;
+       dev->watchdog_timeo = TX_TIMEOUT;
 
-       bp->stats_ticks = 1000000 & 0xffff00;
+       dev->ethtool_ops = &bnx2x_ethtool_ops;
+       dev->open = bnx2x_open;
+       dev->stop = bnx2x_close;
+       dev->set_multicast_list = bnx2x_set_rx_mode;
+       dev->set_mac_address = bnx2x_change_mac_addr;
+       dev->do_ioctl = bnx2x_ioctl;
+       dev->change_mtu = bnx2x_change_mtu;
+       dev->tx_timeout = bnx2x_tx_timeout;
+#ifdef BCM_VLAN
+       dev->vlan_rx_register = bnx2x_vlan_rx_register;
+#endif
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+       dev->poll_controller = poll_bnx2x;
+#endif
+       dev->features |= NETIF_F_SG;
+       dev->features |= NETIF_F_HW_CSUM;
+       if (bp->flags & USING_DAC_FLAG)
+               dev->features |= NETIF_F_HIGHDMA;
+#ifdef BCM_VLAN
+       dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+#endif
+       dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
 
        bp->timer_interval = HZ;
        bp->current_interval = (poll ? poll : HZ);
 
-       init_timer(&bp->timer);
-       bp->timer.expires = jiffies + bp->current_interval;
-       bp->timer.data = (unsigned long) bp;
-       bp->timer.function = bnx2x_timer;
 
        return 0;
 
@@ -7357,14 +8332,14 @@ err_out_unmap:
                iounmap(bp->regview);
                bp->regview = NULL;
        }
-
        if (bp->doorbells) {
                iounmap(bp->doorbells);
                bp->doorbells = NULL;
        }
 
 err_out_release:
-       pci_release_regions(pdev);
+       if (atomic_read(&pdev->enable_cnt) == 1)
+               pci_release_regions(pdev);
 
 err_out_disable:
        pci_disable_device(pdev);
@@ -7398,7 +8373,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        struct net_device *dev = NULL;
        struct bnx2x *bp;
        int rc;
-       int port = PCI_FUNC(pdev->devfn);
        DECLARE_MAC_BUF(mac);
 
        if (version_printed++ == 0)
@@ -7406,78 +8380,62 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
        /* dev zeroed in init_etherdev */
        dev = alloc_etherdev(sizeof(*bp));
-       if (!dev)
+       if (!dev) {
+               printk(KERN_ERR PFX "Cannot allocate net device\n");
                return -ENOMEM;
+       }
 
        netif_carrier_off(dev);
 
        bp = netdev_priv(dev);
        bp->msglevel = debug;
 
-       if (port && onefunc) {
-               printk(KERN_ERR PFX "second function disabled. exiting\n");
-               free_netdev(dev);
-               return 0;
-       }
-
-       rc = bnx2x_init_board(pdev, dev);
+       rc = bnx2x_init_dev(pdev, dev);
        if (rc < 0) {
                free_netdev(dev);
                return rc;
        }
 
-       dev->hard_start_xmit = bnx2x_start_xmit;
-       dev->watchdog_timeo = TX_TIMEOUT;
-
-       dev->ethtool_ops = &bnx2x_ethtool_ops;
-       dev->open = bnx2x_open;
-       dev->stop = bnx2x_close;
-       dev->set_multicast_list = bnx2x_set_rx_mode;
-       dev->set_mac_address = bnx2x_change_mac_addr;
-       dev->do_ioctl = bnx2x_ioctl;
-       dev->change_mtu = bnx2x_change_mtu;
-       dev->tx_timeout = bnx2x_tx_timeout;
-#ifdef BCM_VLAN
-       dev->vlan_rx_register = bnx2x_vlan_rx_register;
-#endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
-       dev->poll_controller = poll_bnx2x;
-#endif
-       dev->features |= NETIF_F_SG;
-       if (bp->flags & USING_DAC_FLAG)
-               dev->features |= NETIF_F_HIGHDMA;
-       dev->features |= NETIF_F_IP_CSUM;
-#ifdef BCM_VLAN
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
-       dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-
        rc = register_netdev(dev);
        if (rc) {
                dev_err(&pdev->dev, "Cannot register net device\n");
-               if (bp->regview)
-                       iounmap(bp->regview);
-               if (bp->doorbells)
-                       iounmap(bp->doorbells);
-               pci_release_regions(pdev);
-               pci_disable_device(pdev);
-               pci_set_drvdata(pdev, NULL);
-               free_netdev(dev);
-               return rc;
+               goto init_one_exit;
        }
 
        pci_set_drvdata(pdev, dev);
 
-       bp->name = board_info[ent->driver_data].name;
+       rc = bnx2x_init_bp(bp);
+       if (rc) {
+               unregister_netdev(dev);
+               goto init_one_exit;
+       }
+
+       bp->common.name = board_info[ent->driver_data].name;
        printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx,"
-              " IRQ %d, ", dev->name, bp->name,
-              ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
-              ((CHIP_ID(bp) & 0x0ff0) >> 4),
+              " IRQ %d, ", dev->name, bp->common.name,
+              (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
               bnx2x_get_pcie_width(bp),
               (bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz",
               dev->base_addr, bp->pdev->irq);
        printk(KERN_CONT "node addr %s\n", print_mac(mac, dev->dev_addr));
        return 0;
+
+init_one_exit:
+       if (bp->regview)
+               iounmap(bp->regview);
+
+       if (bp->doorbells)
+               iounmap(bp->doorbells);
+
+       free_netdev(dev);
+
+       if (atomic_read(&pdev->enable_cnt) == 1)
+               pci_release_regions(pdev);
+
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+
+       return rc;
 }
 
 static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
@@ -7486,11 +8444,9 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
        struct bnx2x *bp;
 
        if (!dev) {
-               /* we get here if init_one() fails */
                printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
                return;
        }
-
        bp = netdev_priv(dev);
 
        unregister_netdev(dev);
@@ -7502,7 +8458,10 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
                iounmap(bp->doorbells);
 
        free_netdev(dev);
-       pci_release_regions(pdev);
+
+       if (atomic_read(&pdev->enable_cnt) == 1)
+               pci_release_regions(pdev);
+
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 }
@@ -7512,21 +8471,29 @@ static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct bnx2x *bp;
 
-       if (!dev)
-               return 0;
+       if (!dev) {
+               printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
+               return -ENODEV;
+       }
+       bp = netdev_priv(dev);
 
-       if (!netif_running(dev))
-               return 0;
+       rtnl_lock();
 
-       bp = netdev_priv(dev);
+       pci_save_state(pdev);
 
-       bnx2x_nic_unload(bp, 0);
+       if (!netif_running(dev)) {
+               rtnl_unlock();
+               return 0;
+       }
 
        netif_device_detach(dev);
 
-       pci_save_state(pdev);
+       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+
        bnx2x_set_power_state(bp, pci_choose_state(pdev, state));
 
+       rtnl_unlock();
+
        return 0;
 }
 
@@ -7540,21 +8507,25 @@ static int bnx2x_resume(struct pci_dev *pdev)
                printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
                return -ENODEV;
        }
-
-       if (!netif_running(dev))
-               return 0;
-
        bp = netdev_priv(dev);
 
+       rtnl_lock();
+
        pci_restore_state(pdev);
+
+       if (!netif_running(dev)) {
+               rtnl_unlock();
+               return 0;
+       }
+
        bnx2x_set_power_state(bp, PCI_D0);
        netif_device_attach(dev);
 
-       rc = bnx2x_nic_load(bp, 0);
-       if (rc)
-               return rc;
+       rc = bnx2x_nic_load(bp, LOAD_NORMAL);
 
-       return 0;
+       rtnl_unlock();
+
+       return rc;
 }
 
 static struct pci_driver bnx2x_pci_driver = {