]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/bnx2x.c
Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6-omap-h63xx.git] / drivers / net / bnx2x.c
index 5cd785064ba322acf5024e9676de9946865d7dc3..8af142ccf373feb060b82fae91e7a5fe9adae10b 100644 (file)
@@ -63,8 +63,8 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 
-#define DRV_MODULE_VERSION      "0.40.15"
-#define DRV_MODULE_RELDATE      "$DateTime: 2007/11/15 07:28:37 $"
+#define DRV_MODULE_VERSION      "1.40.22"
+#define DRV_MODULE_RELDATE      "2007/11/27"
 #define BNX2X_BC_VER           0x040200
 
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -78,7 +78,6 @@ MODULE_AUTHOR("Eliezer Tamir <eliezert@broadcom.com>");
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
-MODULE_INFO(cvs_version, "$Revision: #404 $");
 
 static int use_inta;
 static int poll;
@@ -298,8 +297,7 @@ static void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
 
 static int bnx2x_mc_assert(struct bnx2x *bp)
 {
-       int i, j;
-       int rc = 0;
+       int i, j, rc = 0;
        char last_idx;
        const char storm[] = {"XTCU"};
        const u32 intmem_base[] = {
@@ -313,8 +311,9 @@ static int bnx2x_mc_assert(struct bnx2x *bp)
        for (i = 0; i < 4; i++) {
                last_idx = REG_RD8(bp, XSTORM_ASSERT_LIST_INDEX_OFFSET +
                                   intmem_base[i]);
-               BNX2X_ERR("DATA %cSTORM_ASSERT_LIST_INDEX 0x%x\n",
-                         storm[i], last_idx);
+               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++) {
@@ -330,7 +329,7 @@ static int bnx2x_mc_assert(struct bnx2x *bp)
                                      intmem_base[i]);
 
                        if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
-                               BNX2X_ERR("DATA %cSTORM_ASSERT_INDEX 0x%x ="
+                               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++;
@@ -349,21 +348,22 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
        int word;
 
        mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104);
-       printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark);
+       mark = ((mark + 0x3) & ~0x3);
+       printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark);
 
        for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) {
                for (word = 0; word < 8; word++)
                        data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
                                                  offset + 4*word));
                data[8] = 0x0;
-               printk(KERN_ERR PFX "%s", (char *)data);
+               printk(KERN_CONT "%s", (char *)data);
        }
        for (offset = 0xF108; offset <= mark - 0x08000000; offset += 0x8*4) {
                for (word = 0; word < 8; word++)
                        data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
                                                  offset + 4*word));
                data[8] = 0x0;
-               printk(KERN_ERR PFX "%s", (char *)data);
+               printk(KERN_CONT "%s", (char *)data);
        }
        printk("\n" KERN_ERR PFX "end of fw dump\n");
 }
@@ -428,10 +428,10 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
                }
        }
 
-       BNX2X_ERR("def_c_idx(%u)  def_u_idx(%u)  def_t_idx(%u)"
-                 "  def_x_idx(%u)  def_att_idx(%u)  attn_state(%u)"
+       BNX2X_ERR("def_c_idx(%u)  def_u_idx(%u)  def_x_idx(%u)"
+                 "  def_t_idx(%u)  def_att_idx(%u)  attn_state(%u)"
                  "  spq_prod_idx(%u)\n",
-                 bp->def_c_idx, bp->def_u_idx, bp->def_t_idx, bp->def_x_idx,
+                 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);
 
 
@@ -442,7 +442,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
        DP(BNX2X_MSG_STATS, "stats_state - DISABLE\n");
 }
 
-static void bnx2x_enable_int(struct bnx2x *bp)
+static void bnx2x_int_enable(struct bnx2x *bp)
 {
        int port = bp->port;
        u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
@@ -455,18 +455,26 @@ static void bnx2x_enable_int(struct bnx2x *bp)
                        HC_CONFIG_0_REG_ATTN_BIT_EN_0);
        } else {
                val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
+                       HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
                        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);
+
+               REG_WR(bp, addr, val);
+
                val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0;
        }
 
-       DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)  msi %d\n",
+       DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)  MSI-X %d\n",
           val, port, addr, msix);
 
        REG_WR(bp, addr, val);
 }
 
-static void bnx2x_disable_int(struct bnx2x *bp)
+static void bnx2x_int_disable(struct bnx2x *bp)
 {
        int port = bp->port;
        u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
@@ -485,7 +493,7 @@ static void bnx2x_disable_int(struct bnx2x *bp)
                BNX2X_ERR("BUG! proper val not read from IGU!\n");
 }
 
-static void bnx2x_disable_int_sync(struct bnx2x *bp)
+static void bnx2x_int_disable_sync(struct bnx2x *bp)
 {
 
        int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
@@ -493,7 +501,7 @@ static void bnx2x_disable_int_sync(struct bnx2x *bp)
 
        atomic_inc(&bp->intr_sem);
        /* prevent the HW from sending interrupts */
-       bnx2x_disable_int(bp);
+       bnx2x_int_disable(bp);
 
        /* make sure all ISRs are done */
        if (msix) {
@@ -789,20 +797,20 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
                fp->state = BNX2X_FP_STATE_HALTED;
                break;
 
-       case (RAMROD_CMD_ID_ETH_PORT_DEL | BNX2X_STATE_CLOSING_WAIT4_DELETE):
-               DP(NETIF_MSG_IFDOWN, "got delete ramrod\n");
-               bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
-               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);
-               bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_DELETED;
+               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):
                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");
+               break;
+
        default:
                BNX2X_ERR("unexpected ramrod (%d)  state is %x\n",
                          command, bp->state);
@@ -4080,8 +4088,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
        u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_PORT_BASE * port) * 8;
        u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
                              MISC_REG_AEU_MASK_ATTN_FUNC_0;
-       u32 nig_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
-                                  NIG_REG_MASK_INTERRUPT_PORT0;
+       u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
+                                      NIG_REG_MASK_INTERRUPT_PORT0;
 
        if (~bp->aeu_mask & (asserted & 0xff))
                BNX2X_ERR("IGU ERROR\n");
@@ -4099,15 +4107,11 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 
        if (asserted & ATTN_HARD_WIRED_MASK) {
                if (asserted & ATTN_NIG_FOR_FUNC) {
-                       u32 nig_status_port;
-                       u32 nig_int_addr = port ?
-                                       NIG_REG_STATUS_INTERRUPT_PORT1 :
-                                       NIG_REG_STATUS_INTERRUPT_PORT0;
 
-                       bp->nig_mask = REG_RD(bp, nig_mask_addr);
-                       REG_WR(bp, nig_mask_addr, 0);
+                       /* save nig interrupt mask */
+                       bp->nig_mask = REG_RD(bp, nig_int_mask_addr);
+                       REG_WR(bp, nig_int_mask_addr, 0);
 
-                       nig_status_port = REG_RD(bp, nig_int_addr);
                        bnx2x_link_update(bp);
 
                        /* handle unicore attn? */
@@ -4160,15 +4164,132 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 
        /* now set back the mask */
        if (asserted & ATTN_NIG_FOR_FUNC)
-               REG_WR(bp, nig_mask_addr, bp->nig_mask);
+               REG_WR(bp, nig_int_mask_addr, bp->nig_mask);
 }
 
-static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
+static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
 {
        int port = bp->port;
-       int index;
+       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);
+
+               val = REG_RD(bp, reg_offset);
+               val &= ~AEU_INPUTS_ATTN_BITS_SPIO5;
+               REG_WR(bp, reg_offset, val);
+
+               BNX2X_ERR("SPIO5 hw attention\n");
+
+               switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+               case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
+                       /* Fan failure attention */
+
+                       /* The PHY reset is controled by GPIO 1 */
+                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+                                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
+                       /* Low power mode is controled by GPIO 2 */
+                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
+                       /* mark the failure */
+                       bp->ext_phy_config &=
+                                       ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+                       bp->ext_phy_config |=
+                                       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
+                       SHMEM_WR(bp,
+                                dev_info.port_hw_config[port].
+                                                       external_phy_config,
+                                bp->ext_phy_config);
+                       /* log the failure */
+                       printk(KERN_ERR PFX "Fan Failure on Network"
+                              " Controller %s has caused the driver to"
+                              " shutdown the card to prevent permanent"
+                              " damage.  Please contact Dell Support for"
+                              " assistance\n", bp->dev->name);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
+
+static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
+{
+       u32 val;
+
+       if (attn & BNX2X_DOORQ_ASSERT) {
+
+               val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR);
+               BNX2X_ERR("DB hw attention 0x%x\n", val);
+               /* DORQ discard attention */
+               if (val & 0x2)
+                       BNX2X_ERR("FATAL error from DORQ\n");
+       }
+}
+
+static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
+{
+       u32 val;
+
+       if (attn & AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) {
+
+               val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR);
+               BNX2X_ERR("CFC hw attention 0x%x\n", val);
+               /* CFC error attention */
+               if (val & 0x2)
+                       BNX2X_ERR("FATAL error from CFC\n");
+       }
+
+       if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
+
+               val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
+               BNX2X_ERR("PXP hw attention 0x%x\n", val);
+               /* RQ_USDMDP_FIFO_OVERFLOW */
+               if (val & 0x18000)
+                       BNX2X_ERR("FATAL error from PXP\n");
+       }
+}
+
+static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
+{
+       if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) {
+
+               if (attn & BNX2X_MC_ASSERT_BITS) {
+
+                       BNX2X_ERR("MC assert!\n");
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0);
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0);
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_7, 0);
+                       bnx2x_panic();
+
+               } else if (attn & BNX2X_MCP_ASSERT) {
+
+                       BNX2X_ERR("MCP assert!\n");
+                       REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_11, 0);
+                       bnx2x_mc_assert(bp);
+
+               } else
+                       BNX2X_ERR("Unknown HW assert! (attn 0x%x)\n", attn);
+       }
+
+       if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
+
+               REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
+               BNX2X_ERR("LATCHED attention 0x%x (masked)\n", attn);
+       }
+}
+
+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 index;
        u32 reg_addr;
        u32 val;
 
@@ -4189,64 +4310,14 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
                        DP(NETIF_MSG_HW, "group[%d]: %llx\n", index,
                           (unsigned long long)group_mask.sig[0]);
 
-                       if (attn.sig[3] & group_mask.sig[3] &
-                           EVEREST_GEN_ATTN_IN_USE_MASK) {
-
-                               if (attn.sig[3] & BNX2X_MC_ASSERT_BITS) {
-
-                                       BNX2X_ERR("MC assert!\n");
-                                       bnx2x_panic();
-
-                               } else if (attn.sig[3] & BNX2X_MCP_ASSERT) {
-
-                                       BNX2X_ERR("MCP assert!\n");
-                                       REG_WR(bp,
-                                            MISC_REG_AEU_GENERAL_ATTN_11, 0);
-                                       bnx2x_mc_assert(bp);
-
-                               } else {
-                                       BNX2X_ERR("UNKOWEN HW ASSERT!\n");
-                               }
-                       }
-
-                       if (attn.sig[1] & group_mask.sig[1] &
-                           BNX2X_DOORQ_ASSERT) {
-
-                               val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR);
-                               BNX2X_ERR("DB hw attention 0x%x\n", val);
-                               /* DORQ discard attention */
-                               if (val & 0x2)
-                                       BNX2X_ERR("FATAL error from DORQ\n");
-                       }
-
-                       if (attn.sig[2] & group_mask.sig[2] &
-                           AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) {
-
-                               val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR);
-                               BNX2X_ERR("CFC hw attention 0x%x\n", val);
-                               /* CFC error attention */
-                               if (val & 0x2)
-                                       BNX2X_ERR("FATAL error from CFC\n");
-                       }
-
-                       if (attn.sig[2] & group_mask.sig[2] &
-                           AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
-
-                               val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
-                               BNX2X_ERR("PXP hw attention 0x%x\n", val);
-                               /* RQ_USDMDP_FIFO_OVERFLOW */
-                               if (val & 0x18000)
-                                       BNX2X_ERR("FATAL error from PXP\n");
-                       }
-
-                       if (attn.sig[3] & group_mask.sig[3] &
-                           EVEREST_LATCHED_ATTN_IN_USE_MASK) {
-
-                               REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL,
-                                      0x7ff);
-                               DP(NETIF_MSG_HW, "got latched bits 0x%x\n",
-                                  attn.sig[3]);
-                       }
+                       bnx2x_attn_int_deasserted3(bp,
+                                       attn.sig[3] & group_mask.sig[3]);
+                       bnx2x_attn_int_deasserted1(bp,
+                                       attn.sig[1] & group_mask.sig[1]);
+                       bnx2x_attn_int_deasserted2(bp,
+                                       attn.sig[2] & group_mask.sig[2]);
+                       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) ||
@@ -4254,7 +4325,15 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
                                                HW_INTERRUT_ASSERT_SET_1) ||
                            (attn.sig[2] & group_mask.sig[2] &
                                                HW_INTERRUT_ASSERT_SET_2))
-                               BNX2X_ERR("FATAL HW block attention\n");
+                               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) ||
@@ -4262,7 +4341,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
                                                HW_PRTY_ASSERT_SET_1) ||
                            (attn.sig[2] & group_mask.sig[2] &
                                                HW_PRTY_ASSERT_SET_2))
-                               BNX2X_ERR("FATAL HW block parity attention\n");
+                              BNX2X_ERR("FATAL HW block parity attention\n");
                }
        }
 
@@ -4327,7 +4406,7 @@ static void bnx2x_sp_task(struct work_struct *work)
 
        /* 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");
+               DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
                return;
        }
 
@@ -4337,12 +4416,11 @@ static void bnx2x_sp_task(struct work_struct *work)
 
        DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status);
 
-       if (status & 0x1) {
-               /* HW attentions */
+       /* HW attentions */
+       if (status & 0x1)
                bnx2x_attn_int(bp);
-       }
 
-       /* CStorm events: query_stats, cfc delete ramrods */
+       /* CStorm events: query_stats, port delete ramrod */
        if (status & 0x2)
                bp->stat_pending = 0;
 
@@ -4356,6 +4434,7 @@ static void bnx2x_sp_task(struct work_struct *work)
                     IGU_INT_NOP, 1);
        bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, le16_to_cpu(bp->def_t_idx),
                     IGU_INT_ENABLE, 1);
+
 }
 
 static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
@@ -4365,11 +4444,11 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 
        /* 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");
+               DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
                return IRQ_HANDLED;
        }
 
-       bnx2x_ack_sb(bp, 16, XSTORM_ID, 0, IGU_INT_DISABLE, 0);
+       bnx2x_ack_sb(bp, DEF_SB_ID, XSTORM_ID, 0, IGU_INT_DISABLE, 0);
 
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic))
@@ -4971,39 +5050,37 @@ static void bnx2x_update_net_stats(struct bnx2x *bp)
 
        nstats->rx_bytes = bnx2x_hilo(&estats->total_bytes_received_hi);
 
-       nstats->tx_bytes =
-               bnx2x_hilo(&estats->total_bytes_transmitted_hi);
+       nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
 
-       nstats->rx_dropped = estats->checksum_discard +
-                                  estats->mac_discard;
+       nstats->rx_dropped = estats->checksum_discard + estats->mac_discard;
        nstats->tx_dropped = 0;
 
        nstats->multicast =
                bnx2x_hilo(&estats->total_multicast_packets_transmitted_hi);
 
-       nstats->collisions =
-               estats->single_collision_transmit_frames +
-               estats->multiple_collision_transmit_frames +
-               estats->late_collision_frames +
-               estats->excessive_collision_frames;
+       nstats->collisions = estats->single_collision_transmit_frames +
+                            estats->multiple_collision_transmit_frames +
+                            estats->late_collision_frames +
+                            estats->excessive_collision_frames;
 
        nstats->rx_length_errors = estats->runt_packets_received +
                                   estats->jabber_packets_received;
-       nstats->rx_over_errors = estats->no_buff_discard;
+       nstats->rx_over_errors = estats->brb_discard +
+                                estats->brb_truncate_discard;
        nstats->rx_crc_errors = estats->crc_receive_errors;
        nstats->rx_frame_errors = estats->alignment_errors;
-       nstats->rx_fifo_errors = estats->brb_discard +
-                                      estats->brb_truncate_discard;
+       nstats->rx_fifo_errors = estats->no_buff_discard;
        nstats->rx_missed_errors = estats->xxoverflow_discard;
 
        nstats->rx_errors = nstats->rx_length_errors +
                            nstats->rx_over_errors +
                            nstats->rx_crc_errors +
                            nstats->rx_frame_errors +
-                           nstats->rx_fifo_errors;
+                           nstats->rx_fifo_errors +
+                           nstats->rx_missed_errors;
 
        nstats->tx_aborted_errors = estats->late_collision_frames +
-                                         estats->excessive_collision_frames;
+                                   estats->excessive_collision_frames;
        nstats->tx_carrier_errors = estats->false_carrier_detections;
        nstats->tx_fifo_errors = 0;
        nstats->tx_heartbeat_errors = 0;
@@ -5236,6 +5313,9 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            atten_status_block);
        def_sb->atten_status_block.status_block_id = id;
 
+       bp->def_att_idx = 0;
+       bp->attn_state = 0;
+
        reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
                             MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
 
@@ -5270,6 +5350,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            u_def_status_block);
        def_sb->u_def_status_block.status_block_id = id;
 
+       bp->def_u_idx = 0;
+
        REG_WR(bp, BAR_USTRORM_INTMEM +
               USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
        REG_WR(bp, BAR_USTRORM_INTMEM +
@@ -5287,6 +5369,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            c_def_status_block);
        def_sb->c_def_status_block.status_block_id = id;
 
+       bp->def_c_idx = 0;
+
        REG_WR(bp, BAR_CSTRORM_INTMEM +
               CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
        REG_WR(bp, BAR_CSTRORM_INTMEM +
@@ -5304,6 +5388,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            t_def_status_block);
        def_sb->t_def_status_block.status_block_id = id;
 
+       bp->def_t_idx = 0;
+
        REG_WR(bp, BAR_TSTRORM_INTMEM +
               TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
        REG_WR(bp, BAR_TSTRORM_INTMEM +
@@ -5321,6 +5407,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            x_def_status_block);
        def_sb->x_def_status_block.status_block_id = id;
 
+       bp->def_x_idx = 0;
+
        REG_WR(bp, BAR_XSTRORM_INTMEM +
               XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
        REG_WR(bp, BAR_XSTRORM_INTMEM +
@@ -5333,6 +5421,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                REG_WR16(bp, BAR_XSTRORM_INTMEM +
                         XSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
 
+       bp->stat_pending = 0;
+
        bnx2x_ack_sb(bp, id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
 }
 
@@ -5476,7 +5566,6 @@ static void bnx2x_init_sp_ring(struct bnx2x *bp)
 
        bp->spq_left = MAX_SPQ_PENDING;
        bp->spq_prod_idx = 0;
-       bp->dsb_sp_prod_idx = 0;
        bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
        bp->spq_prod_bd = bp->spq;
        bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT;
@@ -5553,6 +5642,42 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
        REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
 }
 
+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};
+
+       tstorm_client.mtu = bp->dev->mtu;
+       tstorm_client.statistics_counter_id = 0;
+       tstorm_client.config_flags =
+                               TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+#ifdef BCM_VLAN
+       if (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),
+                      ((u32 *)&tstorm_client)[0]);
+               REG_WR(bp, BAR_TSTRORM_INTMEM +
+                      TSTORM_CLIENT_CONFIG_OFFSET(port, i) + 4,
+                      ((u32 *)&tstorm_client)[1]);
+       }
+
+/*     DP(NETIF_MSG_IFUP, "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;
@@ -5592,41 +5717,9 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 /*             DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
                   ((u32 *)&tstorm_mac_filter)[i]); */
        }
-}
-
-static void bnx2x_set_client_config(struct bnx2x *bp, int client_id)
-{
-#ifdef BCM_VLAN
-       int mode = bp->rx_mode;
-#endif
-       int port = bp->port;
-       struct tstorm_eth_client_config tstorm_client = {0};
-
-       tstorm_client.mtu = bp->dev->mtu;
-       tstorm_client.statistics_counter_id = 0;
-       tstorm_client.config_flags =
-               TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
-#ifdef BCM_VLAN
-       if (mode && bp->vlgrp) {
-               tstorm_client.config_flags |=
-                               TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
-               DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
-       }
-#endif
-       tstorm_client.drop_flags = (TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR |
-                                   TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR |
-                                   TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR |
-                                   TSTORM_ETH_CLIENT_CONFIG_DROP_MAC_ERR);
-
-       REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_CLIENT_CONFIG_OFFSET(port, client_id),
-              ((u32 *)&tstorm_client)[0]);
-       REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_CLIENT_CONFIG_OFFSET(port, client_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]); */
+       if (mode != BNX2X_RX_MODE_NONE)
+               bnx2x_set_client_config(bp);
 }
 
 static void bnx2x_init_internal(struct bnx2x *bp)
@@ -5634,7 +5727,6 @@ 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 i;
 
        if (is_multi(bp)) {
                tstorm_config.config_flags = MULTI_FLAGS;
@@ -5651,10 +5743,6 @@ static void bnx2x_init_internal(struct bnx2x *bp)
        bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */
        bnx2x_set_storm_rx_mode(bp);
 
-       for_each_queue(bp, i)
-               bnx2x_set_client_config(bp, i);
-
-
        stats_flags.collect_eth = cpu_to_le32(1);
 
        REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(port),
@@ -5700,7 +5788,7 @@ static void bnx2x_nic_init(struct bnx2x *bp)
        bnx2x_init_internal(bp);
        bnx2x_init_stats(bp);
        bnx2x_init_ind_table(bp);
-       bnx2x_enable_int(bp);
+       bnx2x_int_enable(bp);
 
 }
 
@@ -6792,14 +6880,11 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp)
                   "state(%x)\n", i, bp->msix_table[i + 1].vector,
                   bnx2x_fp(bp, i, state));
 
-               if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED) {
-
-                       free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]);
-                       bnx2x_fp(bp, i, state) = BNX2X_FP_STATE_CLOSED;
-
-               } else
-                       DP(NETIF_MSG_IFDOWN, "irq not freed\n");
+               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]);
        }
 
 }
@@ -6829,7 +6914,7 @@ static int bnx2x_enable_msix(struct bnx2x *bp)
 
        if (pci_enable_msix(bp->pdev, &bp->msix_table[0],
                                     bp->num_queues + 1)){
-               BNX2X_ERR("failed to enable msix\n");
+               BNX2X_LOG("failed to enable MSI-X\n");
                return -1;
 
        }
@@ -6846,8 +6931,6 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
 
        int i, rc;
 
-       DP(NETIF_MSG_IFUP, "about to request sp irq\n");
-
        rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0,
                         bp->dev->name, bp->dev);
 
@@ -6862,7 +6945,8 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
                                 bp->dev->name, &bp->fp[i]);
 
                if (rc) {
-                       BNX2X_ERR("request fp #%d irq failed\n", i);
+                       BNX2X_ERR("request fp #%d irq failed  "
+                                 "rc %d\n", i, rc);
                        bnx2x_free_msix_irqs(bp);
                        return -EBUSY;
                }
@@ -6961,7 +7045,7 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
 
                mb(); /* state is changed by bnx2x_sp_event()*/
 
-               if (*state_p != state)
+               if (*state_p == state)
                        return 0;
 
                timeout--;
@@ -6970,9 +7054,10 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
        }
 
        /* timeout! */
-       BNX2X_ERR("timeout waiting for ramrod %d on %d\n", state, idx);
-       return -EBUSY;
+       BNX2X_ERR("timeout %s for state %x on IDX [%d]\n",
+                 poll ? "polling" : "waiting", state, idx);
 
+       return -EBUSY;
 }
 
 static int bnx2x_setup_leading(struct bnx2x *bp)
@@ -6994,12 +7079,13 @@ 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);
 
+       /* SETUP ramrod */
        bp->fp[index].state = BNX2X_FP_STATE_OPENING;
        bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_SETUP, index, 0, index, 0);
 
        /* Wait for completion */
        return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index,
-                                &(bp->fp[index].state), 1);
+                                &(bp->fp[index].state), 0);
 
 }
 
@@ -7009,8 +7095,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev);
 
 static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 {
-       int rc;
-       int i = 0;
+       u32 load_code;
+       int i;
 
        bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
 
@@ -7020,12 +7106,17 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
           initialized, otherwise - not.
        */
        if (!nomcp) {
-               rc = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
-               if (rc == FW_MSG_CODE_DRV_LOAD_REFUSED) {
+               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");
                        return -EBUSY; /* other port in diagnostic mode */
                }
        } else {
-               rc = FW_MSG_CODE_DRV_LOAD_COMMON;
+               load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
        }
 
        /* if we can't use msix we only need one fp,
@@ -7063,13 +7154,13 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
                if (bp->flags & USING_MSIX_FLAG) {
                        if (bnx2x_req_msix_irqs(bp)) {
                                pci_disable_msix(bp->pdev);
-                               goto out_error;
+                               goto load_error;
                        }
 
                } else {
                        if (bnx2x_req_irq(bp)) {
                                BNX2X_ERR("IRQ request failed, aborting\n");
-                               goto out_error;
+                               goto load_error;
                        }
                }
        }
@@ -7080,9 +7171,10 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 
 
        /* Initialize HW */
-       if (bnx2x_function_init(bp, (rc == FW_MSG_CODE_DRV_LOAD_COMMON))) {
+       if (bnx2x_function_init(bp,
+                               (load_code == FW_MSG_CODE_DRV_LOAD_COMMON))) {
                BNX2X_ERR("HW init failed, aborting\n");
-               goto out_error;
+               goto load_error;
        }
 
 
@@ -7094,11 +7186,10 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 
        /* Send LOAD_DONE command to MCP */
        if (!nomcp) {
-               rc = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
-               DP(NETIF_MSG_IFUP, "rc = 0x%x\n", rc);
-               if (!rc) {
+               load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
+               if (!load_code) {
                        BNX2X_ERR("MCP response failure, unloading\n");
-                       goto int_disable;
+                       goto load_int_disable;
                }
        }
 
@@ -7110,11 +7201,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
                napi_enable(&bnx2x_fp(bp, i, napi));
 
        if (bnx2x_setup_leading(bp))
-               goto stop_netif;
+               goto load_stop_netif;
 
        for_each_nondefault_queue(bp, i)
                if (bnx2x_setup_multi(bp, i))
-                       goto stop_netif;
+                       goto load_stop_netif;
 
        bnx2x_set_mac_addr(bp);
 
@@ -7138,42 +7229,24 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 
        return 0;
 
-stop_netif:
+load_stop_netif:
        for_each_queue(bp, i)
                napi_disable(&bnx2x_fp(bp, i, napi));
 
-int_disable:
-       bnx2x_disable_int_sync(bp);
+load_int_disable:
+       bnx2x_int_disable_sync(bp);
 
        bnx2x_free_skbs(bp);
        bnx2x_free_irq(bp);
 
-out_error:
+load_error:
        bnx2x_free_mem(bp);
 
        /* TBD we really need to reset the chip
           if we want to recover from this */
-       return rc;
+       return -EBUSY;
 }
 
-static void bnx2x_netif_stop(struct bnx2x *bp)
-{
-       int i;
-
-       bp->rx_mode = BNX2X_RX_MODE_NONE;
-       bnx2x_set_storm_rx_mode(bp);
-
-       bnx2x_disable_int_sync(bp);
-       bnx2x_link_reset(bp);
-
-       for_each_queue(bp, i)
-               napi_disable(&bnx2x_fp(bp, i, napi));
-
-       if (netif_running(bp->dev)) {
-               netif_tx_disable(bp->dev);
-               bp->dev->trans_start = jiffies; /* prevent tx timeout */
-       }
-}
 
 static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
 {
@@ -7239,7 +7312,7 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index)
        /* 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_DELETED, index,
+       return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
                                 &(bp->fp[index].state), 1);
 
 }
@@ -7247,7 +7320,7 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index)
 
 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;
@@ -7262,52 +7335,71 @@ static void bnx2x_stop_leading(struct bnx2x *bp)
                               &(bp->fp[0].state), 1))
                return;
 
-       bp->dsb_sp_prod_idx = *bp->dsb_sp_prod;
+       dsb_sp_prod_idx = *bp->dsb_sp_prod;
 
-       /* Send CFC_DELETE ramrod */
+       /* Send PORT_DELETE ramrod */
        bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_DEL, 0, 0, 0, 1);
 
-       /*
-          Wait for completion.
+       /* Wait for completion to arrive on default status block
           we are going to reset the chip anyway
           so there is not much to do if this times out
         */
-       while (bp->dsb_sp_prod_idx == *bp->dsb_sp_prod && timeout) {
-                       timeout--;
-                       msleep(1);
+       while ((dsb_sp_prod_idx == *bp->dsb_sp_prod) && timeout) {
+               timeout--;
+               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);
+       }
+       bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
+       bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
 }
 
-static int bnx2x_nic_unload(struct bnx2x *bp, int fre_irq)
+
+static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq)
 {
        u32 reset_code = 0;
-       int rc;
-       int i;
+       int i, timeout;
 
        bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
 
-       /* Calling flush_scheduled_work() may deadlock because
-        * linkwatch_event() may be on the workqueue and it will try to get
-        * the rtnl_lock which we are holding.
-        */
+       del_timer_sync(&bp->timer);
 
-       while (bp->in_reset_task)
-               msleep(1);
+       bp->rx_mode = BNX2X_RX_MODE_NONE;
+       bnx2x_set_storm_rx_mode(bp);
 
-       /* Delete the timer: do it before disabling interrupts, as it
-          may be still STAT_QUERY ramrod pending after stopping the timer */
-       del_timer_sync(&bp->timer);
+       if (netif_running(bp->dev)) {
+               netif_tx_disable(bp->dev);
+               bp->dev->trans_start = jiffies; /* prevent tx timeout */
+       }
+
+       /* 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--))
+                       msleep(1);
+               if (!timeout)
+                       BNX2X_ERR("timeout waiting for queue[%d]\n", i);
+       }
 
        /* Wait until stat ramrod returns and all SP tasks complete */
-       while (bp->stat_pending && (bp->spq_left != MAX_SPQ_PENDING))
+       timeout = 1000;
+       while ((bp->stat_pending || (bp->spq_left != MAX_SPQ_PENDING)) &&
+              (timeout--))
                msleep(1);
 
-       /* Stop fast path, disable MAC, disable interrupts, disable napi */
-       bnx2x_netif_stop(bp);
+       for_each_queue(bp, i)
+               napi_disable(&bnx2x_fp(bp, i, napi));
+       /* Disable interrupts after Tx and Rx are disabled on stack level */
+       bnx2x_int_disable_sync(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;
                u8 *mac_addr = bp->dev->dev_addr;
@@ -7324,28 +7416,37 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int fre_irq)
                EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 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 */
        for_each_nondefault_queue(bp, i)
                if (bnx2x_stop_multi(bp, i))
-                       goto error;
-
+                       goto unload_error;
 
        bnx2x_stop_leading(bp);
+       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",
+                  bp->state, bp->fp[0].state);
+       }
+
+unload_error:
+       bnx2x_link_reset(bp);
 
-error:
        if (!nomcp)
-               rc = bnx2x_fw_command(bp, reset_code);
+               reset_code = bnx2x_fw_command(bp, reset_code);
        else
-               rc = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+               reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
 
        /* Release IRQs */
-       if (fre_irq)
+       if (free_irq)
                bnx2x_free_irq(bp);
 
        /* Reset the chip */
-       bnx2x_reset_chip(bp, rc);
+       bnx2x_reset_chip(bp, reset_code);
 
        /* Report UNLOAD_DONE to MCP */
        if (!nomcp)
@@ -7356,8 +7457,7 @@ error:
        bnx2x_free_mem(bp);
 
        bp->state = BNX2X_STATE_CLOSED;
-       /* Set link down */
-       bp->link_up = 0;
+
        netif_carrier_off(bp->dev);
 
        return 0;
@@ -8736,81 +8836,87 @@ static void bnx2x_self_test(struct net_device *dev,
 static struct {
        char string[ETH_GSTRING_LEN];
 } bnx2x_stats_str_arr[BNX2X_NUM_STATS] = {
-       { "rx_bytes"},                           /*  0 */
-       { "rx_error_bytes"},                     /*  1 */
-       { "tx_bytes"},                           /*  2 */
-       { "tx_error_bytes"},                     /*  3 */
-       { "rx_ucast_packets"},                   /*  4 */
-       { "rx_mcast_packets"},                   /*  5 */
-       { "rx_bcast_packets"},                   /*  6 */
-       { "tx_ucast_packets"},                   /*  7 */
-       { "tx_mcast_packets"},                   /*  8 */
-       { "tx_bcast_packets"},                   /*  9 */
-       { "tx_mac_errors"},                      /* 10 */
-       { "tx_carrier_errors"},                  /* 11 */
-       { "rx_crc_errors"},                      /* 12 */
-       { "rx_align_errors"},                    /* 13 */
-       { "tx_single_collisions"},               /* 14 */
-       { "tx_multi_collisions"},                /* 15 */
-       { "tx_deferred"},                        /* 16 */
-       { "tx_excess_collisions"},               /* 17 */
-       { "tx_late_collisions"},                 /* 18 */
-       { "tx_total_collisions"},                /* 19 */
-       { "rx_fragments"},                       /* 20 */
-       { "rx_jabbers"},                         /* 21 */
-       { "rx_undersize_packets"},               /* 22 */
-       { "rx_oversize_packets"},                /* 23 */
-       { "rx_xon_frames"},                      /* 24 */
-       { "rx_xoff_frames"},                     /* 25 */
-       { "tx_xon_frames"},                      /* 26 */
-       { "tx_xoff_frames"},                     /* 27 */
-       { "rx_mac_ctrl_frames"},                 /* 28 */
-       { "rx_filtered_packets"},                /* 29 */
-       { "rx_discards"},                        /* 30 */
+       { "rx_bytes"},
+       { "rx_error_bytes"},
+       { "tx_bytes"},
+       { "tx_error_bytes"},
+       { "rx_ucast_packets"},
+       { "rx_mcast_packets"},
+       { "rx_bcast_packets"},
+       { "tx_ucast_packets"},
+       { "tx_mcast_packets"},
+       { "tx_bcast_packets"},
+       { "tx_mac_errors"},     /* 10 */
+       { "tx_carrier_errors"},
+       { "rx_crc_errors"},
+       { "rx_align_errors"},
+       { "tx_single_collisions"},
+       { "tx_multi_collisions"},
+       { "tx_deferred"},
+       { "tx_excess_collisions"},
+       { "tx_late_collisions"},
+       { "tx_total_collisions"},
+       { "rx_fragments"},      /* 20 */
+       { "rx_jabbers"},
+       { "rx_undersize_packets"},
+       { "rx_oversize_packets"},
+       { "rx_xon_frames"},
+       { "rx_xoff_frames"},
+       { "tx_xon_frames"},
+       { "tx_xoff_frames"},
+       { "rx_mac_ctrl_frames"},
+       { "rx_filtered_packets"},
+       { "rx_discards"},       /* 30 */
+       { "brb_discard"},
+       { "brb_truncate"},
+       { "xxoverflow"}
 };
 
 #define STATS_OFFSET32(offset_name) \
        (offsetof(struct bnx2x_eth_stats, offset_name) / 4)
 
 static unsigned long bnx2x_stats_offset_arr[BNX2X_NUM_STATS] = {
-       STATS_OFFSET32(total_bytes_received_hi),                     /*  0 */
-       STATS_OFFSET32(stat_IfHCInBadOctets_hi),                     /*  1 */
-       STATS_OFFSET32(total_bytes_transmitted_hi),                  /*  2 */
-       STATS_OFFSET32(stat_IfHCOutBadOctets_hi),                    /*  3 */
-       STATS_OFFSET32(total_unicast_packets_received_hi),           /*  4 */
-       STATS_OFFSET32(total_multicast_packets_received_hi),         /*  5 */
-       STATS_OFFSET32(total_broadcast_packets_received_hi),         /*  6 */
-       STATS_OFFSET32(total_unicast_packets_transmitted_hi),        /*  7 */
-       STATS_OFFSET32(total_multicast_packets_transmitted_hi),      /*  8 */
-       STATS_OFFSET32(total_broadcast_packets_transmitted_hi),      /*  9 */
-       STATS_OFFSET32(stat_Dot3statsInternalMacTransmitErrors),     /* 10 */
-       STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors),            /* 11 */
-       STATS_OFFSET32(crc_receive_errors),                          /* 12 */
-       STATS_OFFSET32(alignment_errors),                            /* 13 */
-       STATS_OFFSET32(single_collision_transmit_frames),            /* 14 */
-       STATS_OFFSET32(multiple_collision_transmit_frames),          /* 15 */
-       STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions),         /* 16 */
-       STATS_OFFSET32(excessive_collision_frames),                  /* 17 */
-       STATS_OFFSET32(late_collision_frames),                       /* 18 */
-       STATS_OFFSET32(number_of_bugs_found_in_stats_spec),          /* 19 */
-       STATS_OFFSET32(runt_packets_received),                       /* 20 */
-       STATS_OFFSET32(jabber_packets_received),                     /* 21 */
-       STATS_OFFSET32(error_runt_packets_received),                 /* 22 */
-       STATS_OFFSET32(error_jabber_packets_received),               /* 23 */
-       STATS_OFFSET32(pause_xon_frames_received),                   /* 24 */
-       STATS_OFFSET32(pause_xoff_frames_received),                  /* 25 */
-       STATS_OFFSET32(pause_xon_frames_transmitted),                /* 26 */
-       STATS_OFFSET32(pause_xoff_frames_transmitted),               /* 27 */
-       STATS_OFFSET32(control_frames_received),                     /* 28 */
-       STATS_OFFSET32(mac_filter_discard),                          /* 29 */
-       STATS_OFFSET32(no_buff_discard),                             /* 30 */
+       STATS_OFFSET32(total_bytes_received_hi),
+       STATS_OFFSET32(stat_IfHCInBadOctets_hi),
+       STATS_OFFSET32(total_bytes_transmitted_hi),
+       STATS_OFFSET32(stat_IfHCOutBadOctets_hi),
+       STATS_OFFSET32(total_unicast_packets_received_hi),
+       STATS_OFFSET32(total_multicast_packets_received_hi),
+       STATS_OFFSET32(total_broadcast_packets_received_hi),
+       STATS_OFFSET32(total_unicast_packets_transmitted_hi),
+       STATS_OFFSET32(total_multicast_packets_transmitted_hi),
+       STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
+       STATS_OFFSET32(stat_Dot3statsInternalMacTransmitErrors), /* 10 */
+       STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors),
+       STATS_OFFSET32(crc_receive_errors),
+       STATS_OFFSET32(alignment_errors),
+       STATS_OFFSET32(single_collision_transmit_frames),
+       STATS_OFFSET32(multiple_collision_transmit_frames),
+       STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions),
+       STATS_OFFSET32(excessive_collision_frames),
+       STATS_OFFSET32(late_collision_frames),
+       STATS_OFFSET32(number_of_bugs_found_in_stats_spec),
+       STATS_OFFSET32(runt_packets_received),                  /* 20 */
+       STATS_OFFSET32(jabber_packets_received),
+       STATS_OFFSET32(error_runt_packets_received),
+       STATS_OFFSET32(error_jabber_packets_received),
+       STATS_OFFSET32(pause_xon_frames_received),
+       STATS_OFFSET32(pause_xoff_frames_received),
+       STATS_OFFSET32(pause_xon_frames_transmitted),
+       STATS_OFFSET32(pause_xoff_frames_transmitted),
+       STATS_OFFSET32(control_frames_received),
+       STATS_OFFSET32(mac_filter_discard),
+       STATS_OFFSET32(no_buff_discard),                        /* 30 */
+       STATS_OFFSET32(brb_discard),
+       STATS_OFFSET32(brb_truncate_discard),
+       STATS_OFFSET32(xxoverflow_discard)
 };
 
 static u8 bnx2x_stats_len_arr[BNX2X_NUM_STATS] = {
        8, 0, 8, 0, 8, 8, 8, 8, 8, 8,
        4, 0, 4, 4, 4, 4, 4, 4, 4, 4,
        4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-       4,
+       4, 4, 4, 4
 };
 
 static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
@@ -8968,9 +9074,7 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
  * net_device service functions
  */
 
-/* Called with rtnl_lock from vlan functions and also netif_tx_lock
- * from set_multicast.
- */
+/* called with netif_tx_lock from set_multicast */
 static void bnx2x_set_rx_mode(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
@@ -9164,7 +9268,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                /* for now NS flag is not used in Linux */
                pbd->global_data = (len |
-                                   ((skb->protocol == ETH_P_8021Q) <<
+                                   ((skb->protocol == ntohs(ETH_P_8021Q)) <<
                                     ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT));
                pbd->ip_hlen = ip_hdrlen(skb) / 2;
                pbd->total_hlen = cpu_to_le16(len + pbd->ip_hlen);
@@ -9173,7 +9277,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                        tx_bd->bd_flags.as_bitfield |=
                                                ETH_TX_BD_FLAGS_TCP_CSUM;
-                       pbd->tcp_flags = htonl(tcp_flag_word(skb)) & 0xFFFF;
+                       pbd->tcp_flags = pbd_tcp_flags(skb);
                        pbd->total_hlen += cpu_to_le16(tcp_hdrlen(skb) / 2);
                        pbd->tcp_pseudo_csum = swab16(th->check);
 
@@ -9217,7 +9321,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (skb_shinfo(skb)->gso_size &&
            (skb->len > (bp->dev->mtu + ETH_HLEN))) {
-               int hlen = 2 * le32_to_cpu(pbd->total_hlen);
+               int hlen = 2 * le16_to_cpu(pbd->total_hlen);
 
                DP(NETIF_MSG_TX_QUEUED,
                   "TSO packet len %d  hlen %d  total len %d  tso size %d\n",
@@ -9334,9 +9438,11 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %u  bd %d\n", nbd, bd_prod);
 
-       fp->hw_tx_prods->bds_prod += cpu_to_le16(nbd);
+       fp->hw_tx_prods->bds_prod =
+               cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd);
        mb(); /* FW restriction: must not reorder writing nbd and packets */
-       fp->hw_tx_prods->packets_prod += cpu_to_le32(1);
+       fp->hw_tx_prods->packets_prod =
+               cpu_to_le32(le32_to_cpu(fp->hw_tx_prods->packets_prod) + 1);
        DOORBELL(bp, fp_index, 0);
 
        mmiowb();
@@ -9355,11 +9461,6 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static struct net_device_stats *bnx2x_get_stats(struct net_device *dev)
-{
-       return &dev->stats;
-}
-
 /* Called with rtnl_lock */
 static int bnx2x_open(struct net_device *dev)
 {
@@ -9373,16 +9474,13 @@ static int bnx2x_open(struct net_device *dev)
 /* Called with rtnl_lock */
 static int bnx2x_close(struct net_device *dev)
 {
-       int rc;
        struct bnx2x *bp = netdev_priv(dev);
 
        /* Unload the driver, release IRQs */
-       rc = bnx2x_nic_unload(bp, 1);
-       if (rc) {
-               BNX2X_ERR("bnx2x_nic_unload failed: %d\n", rc);
-               return rc;
-       }
-       bnx2x_set_power_state(bp, PCI_D3hot);
+       bnx2x_nic_unload(bp, 1);
+
+       if (!CHIP_REV_IS_SLOW(bp))
+               bnx2x_set_power_state(bp, PCI_D3hot);
 
        return 0;
 }
@@ -9496,7 +9594,7 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
 
        bp->vlgrp = vlgrp;
        if (netif_running(dev))
-               bnx2x_set_rx_mode(dev);
+               bnx2x_set_client_config(bp);
 }
 #endif
 
@@ -9525,14 +9623,18 @@ static void bnx2x_reset_task(struct work_struct *work)
        if (!netif_running(bp->dev))
                return;
 
-       bp->in_reset_task = 1;
+       rtnl_lock();
 
-       bnx2x_netif_stop(bp);
+       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);
 
-       bp->in_reset_task = 0;
+reset_task_exit:
+       rtnl_unlock();
 }
 
 static int __devinit bnx2x_init_board(struct pci_dev *pdev,
@@ -9613,8 +9715,6 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
 
        spin_lock_init(&bp->phy_lock);
 
-       bp->in_reset_task = 0;
-
        INIT_WORK(&bp->reset_task, bnx2x_reset_task);
        INIT_WORK(&bp->sp_task, bnx2x_sp_task);
 
@@ -9767,7 +9867,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        dev->hard_start_xmit = bnx2x_start_xmit;
        dev->watchdog_timeo = TX_TIMEOUT;
 
-       dev->get_stats = bnx2x_get_stats;
        dev->ethtool_ops = &bnx2x_ethtool_ops;
        dev->open = bnx2x_open;
        dev->stop = bnx2x_close;
@@ -9822,10 +9921,16 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct bnx2x *bp = netdev_priv(dev);
+       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);
 
-       flush_scheduled_work();
-       /*tasklet_kill(&bp->sp_task);*/
        unregister_netdev(dev);
 
        if (bp->regview)
@@ -9843,34 +9948,43 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
 static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct bnx2x *bp = netdev_priv(dev);
-       int rc;
+       struct bnx2x *bp;
+
+       if (!dev)
+               return 0;
 
        if (!netif_running(dev))
                return 0;
 
-       rc = bnx2x_nic_unload(bp, 0);
-       if (!rc)
-               return rc;
+       bp = netdev_priv(dev);
+
+       bnx2x_nic_unload(bp, 0);
 
        netif_device_detach(dev);
-       pci_save_state(pdev);
 
+       pci_save_state(pdev);
        bnx2x_set_power_state(bp, pci_choose_state(pdev, state));
+
        return 0;
 }
 
 static int bnx2x_resume(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct bnx2x *bp = netdev_priv(dev);
+       struct bnx2x *bp;
        int rc;
 
+       if (!dev) {
+               printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
+               return -ENODEV;
+       }
+
        if (!netif_running(dev))
                return 0;
 
-       pci_restore_state(pdev);
+       bp = netdev_priv(dev);
 
+       pci_restore_state(pdev);
        bnx2x_set_power_state(bp, PCI_D0);
        netif_device_attach(dev);