Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2010

kernel-2.6.18-194.11.1.el5.src.rpm

From: Andy Gospodarek <gospo@redhat.com>
Date: Mon, 31 Mar 2008 09:31:20 -0400
Subject: [net] bnx2x: update 5.2 to support latest firmware
Message-id: 20080331133120.GG27259@gospo.usersys.redhat.com
O-Subject: [RHEL5.2 PATCH] bnx2x: update to support latest firmware
Bugzilla: 435261

This is a large change late in the development cycle, but Broadcom has
determined it is critical that we include it in 5.2.  The bootcode used
on bnx2x cards shipping in the next month will be incompatible with the
current driver, so we need to update our driver since the current
bootcode should never exist in the wild.

These changes were committed to Dave's net-2.6 tree on Feb 28 and should
be in 2.6.25.

I have upgraded my card and done some basic testing, but I am still
waiting for some feedback from Broadcom to make sure there are no
issues.

This resolves BZ 435261.

Acked-by: Jeff Garzik <jgarzik@redhat.com>

diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c
index 1d2de98..192f229 100644
--- a/drivers/net/bnx2x.c
+++ b/drivers/net/bnx2x.c
@@ -1,6 +1,6 @@
 /* bnx2x.c: Broadcom Everest network driver.
  *
- * Copyright (c) 2007 Broadcom Corporation
+ * Copyright (c) 2007-2008 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -10,13 +10,13 @@
  * Based on code from Michael Chan's bnx2 driver
  * UDP CSUM errata workaround by Arik Gendelman
  * Slowpath rework by Vladislav Zolotarov
- * Statistics and Link managment by Yitchak Gertner
+ * Statistics and Link management by Yitchak Gertner
  *
  */
 
 /* define this to make the driver freeze on error
  * to allow getting debug info
- * (you will need to reboot afterwords)
+ * (you will need to reboot afterwards)
  */
 /*#define BNX2X_STOP_ON_ERROR*/
 
@@ -63,22 +63,21 @@
 #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 BNX2X_BC_VER    	0x040009
+#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. */
 #define TX_TIMEOUT      	(5*HZ)
 
-static const char version[] __devinitdata =
-	"Broadcom NetXtreme II 577xx 10Gigabit Ethernet Driver "
+static char version[] __devinitdata =
+	"Broadcom NetXtreme II 5771X 10Gigabit Ethernet Driver "
 	DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 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: #356 $");
 
 static int use_inta;
 static int poll;
@@ -94,8 +93,8 @@ module_param(debug, 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 managment CPU (Implies onefunc)");
-MODULE_PARM_DESC(debug, "defualt debug msglevel");
+MODULE_PARM_DESC(nomcp, "ignore management CPU (Implies onefunc)");
+MODULE_PARM_DESC(debug, "default debug msglevel");
 
 #ifdef BNX2X_MULTI
 module_param(use_multi, int, 0);
@@ -107,7 +106,7 @@ enum bnx2x_board_type {
 };
 
 /* indexed by board_t, above */
-static const struct {
+static struct {
 	char *name;
 } board_info[] __devinitdata = {
 	{ "Broadcom NetXtreme II BCM57710 XGb" }
@@ -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++;
@@ -341,6 +340,7 @@ static int bnx2x_mc_assert(struct bnx2x *bp)
 	}
 	return rc;
 }
+
 static void bnx2x_fw_dump(struct bnx2x *bp)
 {
 	u32 mark, offset;
@@ -348,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_ERR "%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_ERR "%s", (char *)data);
 	}
 	printk("\n" KERN_ERR PFX "end of fw dump\n");
 }
@@ -427,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);
 
 
@@ -441,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;
@@ -454,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;
@@ -484,15 +493,15 @@ 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;
 	int i;
 
 	atomic_inc(&bp->intr_sem);
-	/* prevent the HW from sending interrupts*/
-	bnx2x_disable_int(bp);
+	/* prevent the HW from sending interrupts */
+	bnx2x_int_disable(bp);
 
 	/* make sure all ISRs are done */
 	if (msix) {
@@ -775,6 +784,7 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
 		mb(); /* force bnx2x_wait_ramrod to see the change */
 		return;
 	}
+
 	switch (command | bp->state) {
 	case (RAMROD_CMD_ID_ETH_PORT_SETUP | BNX2X_STATE_OPENING_WAIT4_PORT):
 		DP(NETIF_MSG_IFUP, "got setup ramrod\n");
@@ -787,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);
@@ -1181,12 +1191,175 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
 	return val;
 }
 
+static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource)
+{
+	u32 cnt;
+	u32 lock_status;
+	u32 resource_bit = (1 << resource);
+	u8 func = bp->port;
+
+	/* Validating that the resource is within range */
+	if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
+		DP(NETIF_MSG_HW,
+		   "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
+		   resource, HW_LOCK_MAX_RESOURCE_VALUE);
+		return -EINVAL;
+	}
+
+	/* Validating that the resource is not already taken */
+	lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8);
+	if (lock_status & resource_bit) {
+		DP(NETIF_MSG_HW, "lock_status 0x%x  resource_bit 0x%x\n",
+		   lock_status, resource_bit);
+		return -EEXIST;
+	}
+
+	/* Try for 1 second every 5ms */
+	for (cnt = 0; cnt < 200; cnt++) {
+		/* Try to acquire the lock */
+		REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + func*8 + 4,
+		       resource_bit);
+		lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8);
+		if (lock_status & resource_bit)
+			return 0;
+
+		msleep(5);
+	}
+	DP(NETIF_MSG_HW, "Timeout\n");
+	return -EAGAIN;
+}
+
+static int bnx2x_hw_unlock(struct bnx2x *bp, u32 resource)
+{
+	u32 lock_status;
+	u32 resource_bit = (1 << resource);
+	u8 func = bp->port;
+
+	/* Validating that the resource is within range */
+	if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
+		DP(NETIF_MSG_HW,
+		   "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
+		   resource, HW_LOCK_MAX_RESOURCE_VALUE);
+		return -EINVAL;
+	}
+
+	/* Validating that the resource is currently taken */
+	lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8);
+	if (!(lock_status & resource_bit)) {
+		DP(NETIF_MSG_HW, "lock_status 0x%x  resource_bit 0x%x\n",
+		   lock_status, resource_bit);
+		return -EFAULT;
+	}
+
+	REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + func*8, resource_bit);
+	return 0;
+}
+
+static 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;
+	int gpio_shift = gpio_num +
+			(gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
+	u32 gpio_mask = (1 << gpio_shift);
+	u32 gpio_reg;
+
+	if (gpio_num > MISC_REGISTERS_GPIO_3) {
+		BNX2X_ERR("Invalid GPIO %d\n", gpio_num);
+		return -EINVAL;
+	}
+
+	bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+	/* read GPIO and mask except the float bits */
+	gpio_reg = (REG_RD(bp, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT);
+
+	switch (mode) {
+	case MISC_REGISTERS_GPIO_OUTPUT_LOW:
+		DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output low\n",
+		   gpio_num, gpio_shift);
+		/* clear FLOAT and set CLR */
+		gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
+		gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS);
+		break;
+
+	case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
+		DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output high\n",
+		   gpio_num, gpio_shift);
+		/* clear FLOAT and set SET */
+		gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
+		gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_SET_POS);
+		break;
+
+	case MISC_REGISTERS_GPIO_INPUT_HI_Z :
+		DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> input\n",
+		   gpio_num, gpio_shift);
+		/* set FLOAT */
+		gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
+		break;
+
+	default:
+		break;
+	}
+
+	REG_WR(bp, MISC_REG_GPIO, gpio_reg);
+	bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_GPIO);
+
+	return 0;
+}
+
+static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
+{
+	u32 spio_mask = (1 << spio_num);
+	u32 spio_reg;
+
+	if ((spio_num < MISC_REGISTERS_SPIO_4) ||
+	    (spio_num > MISC_REGISTERS_SPIO_7)) {
+		BNX2X_ERR("Invalid SPIO %d\n", spio_num);
+		return -EINVAL;
+	}
+
+	bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
+	/* read SPIO and mask except the float bits */
+	spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT);
+
+	switch (mode) {
+	case MISC_REGISTERS_SPIO_OUTPUT_LOW :
+		DP(NETIF_MSG_LINK, "Set SPIO %d -> output low\n", spio_num);
+		/* clear FLOAT and set CLR */
+		spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
+		spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_CLR_POS);
+		break;
+
+	case MISC_REGISTERS_SPIO_OUTPUT_HIGH :
+		DP(NETIF_MSG_LINK, "Set SPIO %d -> output high\n", spio_num);
+		/* clear FLOAT and set SET */
+		spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
+		spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_SET_POS);
+		break;
+
+	case MISC_REGISTERS_SPIO_INPUT_HI_Z:
+		DP(NETIF_MSG_LINK, "Set SPIO %d -> input\n", spio_num);
+		/* set FLOAT */
+		spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
+		break;
+
+	default:
+		break;
+	}
+
+	REG_WR(bp, MISC_REG_SPIO, spio_reg);
+	bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_SPIO);
+
+	return 0;
+}
+
 static int bnx2x_mdio22_write(struct bnx2x *bp, u32 reg, u32 val)
 {
-	int rc;
-	u32 tmp, i;
 	int port = bp->port;
 	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+	u32 tmp;
+	int i, rc;
 
 /*      DP(NETIF_MSG_HW, "phy_addr 0x%x  reg 0x%x  val 0x%08x\n",
 	   bp->phy_addr, reg, val); */
@@ -1238,8 +1411,8 @@ static int bnx2x_mdio22_read(struct bnx2x *bp, u32 reg, u32 *ret_val)
 {
 	int port = bp->port;
 	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	u32 val, i;
-	int rc;
+	u32 val;
+	int i, rc;
 
 	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
 
@@ -1288,58 +1461,54 @@ static int bnx2x_mdio22_read(struct bnx2x *bp, u32 reg, u32 *ret_val)
 	return rc;
 }
 
-static int bnx2x_mdio45_write(struct bnx2x *bp, u32 reg, u32 addr, u32 val)
+static int bnx2x_mdio45_ctrl_write(struct bnx2x *bp, u32 mdio_ctrl,
+				   u32 phy_addr, u32 reg, u32 addr, u32 val)
 {
-	int rc = 0;
-	u32 tmp, i;
-	int port = bp->port;
-	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-
-	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
-
-		tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-		tmp &= ~EMAC_MDIO_MODE_AUTO_POLL;
-		EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp);
-		REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-		udelay(40);
-	}
+	u32 tmp;
+	int i, rc = 0;
 
-	/* set clause 45 mode */
-	tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-	tmp |= EMAC_MDIO_MODE_CLAUSE_45;
-	EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp);
+	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	 * (a value of 49==0x31) and make sure that the AUTO poll is off
+	 */
+	tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	tmp &= ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
+	tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
+		(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
+	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
+	REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	udelay(40);
 
 	/* address */
-	tmp = ((bp->phy_addr << 21) | (reg << 16) | addr |
+	tmp = ((phy_addr << 21) | (reg << 16) | addr |
 	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
 	       EMAC_MDIO_COMM_START_BUSY);
-	EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, tmp);
+	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
 
 	for (i = 0; i < 50; i++) {
 		udelay(10);
 
-		tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM);
+		tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 			udelay(5);
 			break;
 		}
 	}
-
 	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
 		BNX2X_ERR("write phy register failed\n");
 
 		rc = -EBUSY;
+
 	} else {
 		/* data */
-		tmp = ((bp->phy_addr << 21) | (reg << 16) | val |
+		tmp = ((phy_addr << 21) | (reg << 16) | val |
 		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
 		       EMAC_MDIO_COMM_START_BUSY);
-		EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, tmp);
+		REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
 
 		for (i = 0; i < 50; i++) {
 			udelay(10);
 
-			tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM);
+			tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 				udelay(5);
 				break;
@@ -1353,75 +1522,78 @@ static int bnx2x_mdio45_write(struct bnx2x *bp, u32 reg, u32 addr, u32 val)
 		}
 	}
 
-	/* unset clause 45 mode */
-	tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-	tmp &= ~EMAC_MDIO_MODE_CLAUSE_45;
-	EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp);
-
-	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
-
-		tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
+	/* unset clause 45 mode, set the MDIO clock to a faster value
+	 * (0x13 => 6.25Mhz) and restore the AUTO poll if needed
+	 */
+	tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	tmp &= ~(EMAC_MDIO_MODE_CLAUSE_45 | EMAC_MDIO_MODE_CLOCK_CNT);
+	tmp |= (0x13 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG)
 		tmp |= EMAC_MDIO_MODE_AUTO_POLL;
-		EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp);
-	}
+	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
 
 	return rc;
 }
 
-static int bnx2x_mdio45_read(struct bnx2x *bp, u32 reg, u32 addr,
-			     u32 *ret_val)
+static int bnx2x_mdio45_write(struct bnx2x *bp, u32 phy_addr, u32 reg,
+			      u32 addr, u32 val)
 {
-	int port = bp->port;
-	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	u32 val, i;
-	int rc = 0;
+	u32 emac_base = bp->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
 
-	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+	return bnx2x_mdio45_ctrl_write(bp, emac_base, phy_addr,
+				       reg, addr, val);
+}
 
-		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-		val &= ~EMAC_MDIO_MODE_AUTO_POLL;
-		EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val);
-		REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-		udelay(40);
-	}
+static int bnx2x_mdio45_ctrl_read(struct bnx2x *bp, u32 mdio_ctrl,
+				  u32 phy_addr, u32 reg, u32 addr,
+				  u32 *ret_val)
+{
+	u32 val;
+	int i, rc = 0;
 
-	/* set clause 45 mode */
-	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-	val |= EMAC_MDIO_MODE_CLAUSE_45;
-	EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val);
+	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	 * (a value of 49==0x31) and make sure that the AUTO poll is off
+	 */
+	val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	val &= ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
+	val |= (EMAC_MDIO_MODE_CLAUSE_45 |
+		(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
+	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
+	REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	udelay(40);
 
 	/* address */
-	val = ((bp->phy_addr << 21) | (reg << 16) | addr |
+	val = ((phy_addr << 21) | (reg << 16) | addr |
 	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
 	       EMAC_MDIO_COMM_START_BUSY);
-	EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, val);
+	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
 
 	for (i = 0; i < 50; i++) {
 		udelay(10);
 
-		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM);
+		val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
 			udelay(5);
 			break;
 		}
 	}
-
 	if (val & EMAC_MDIO_COMM_START_BUSY) {
 		BNX2X_ERR("read phy register failed\n");
 
 		*ret_val = 0;
 		rc = -EBUSY;
+
 	} else {
 		/* data */
-		val = ((bp->phy_addr << 21) | (reg << 16) |
+		val = ((phy_addr << 21) | (reg << 16) |
 		       EMAC_MDIO_COMM_COMMAND_READ_45 |
 		       EMAC_MDIO_COMM_START_BUSY);
-		EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, val);
+		REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
 
 		for (i = 0; i < 50; i++) {
 			udelay(10);
 
-			val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM);
+			val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
 				val &= EMAC_MDIO_COMM_DATA;
 				break;
@@ -1438,31 +1610,39 @@ static int bnx2x_mdio45_read(struct bnx2x *bp, u32 reg, u32 addr,
 		*ret_val = val;
 	}
 
-	/* unset clause 45 mode */
-	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-	val &= ~EMAC_MDIO_MODE_CLAUSE_45;
-	EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val);
-
-	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
-
-		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
+	/* unset clause 45 mode, set the MDIO clock to a faster value
+	 * (0x13 => 6.25Mhz) and restore the AUTO poll if needed
+	 */
+	val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	val &= ~(EMAC_MDIO_MODE_CLAUSE_45 | EMAC_MDIO_MODE_CLOCK_CNT);
+	val |= (0x13 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+	if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG)
 		val |= EMAC_MDIO_MODE_AUTO_POLL;
-		EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val);
-	}
+	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
 
 	return rc;
 }
 
-static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val)
+static int bnx2x_mdio45_read(struct bnx2x *bp, u32 phy_addr, u32 reg,
+			     u32 addr, u32 *ret_val)
+{
+	u32 emac_base = bp->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
+	return bnx2x_mdio45_ctrl_read(bp, emac_base, phy_addr,
+				      reg, addr, ret_val);
+}
+
+static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 phy_addr, u32 reg,
+			       u32 addr, u32 val)
 {
 	int i;
 	u32 rd_val;
 
 	might_sleep();
 	for (i = 0; i < 10; i++) {
-		bnx2x_mdio45_write(bp, reg, addr, val);
+		bnx2x_mdio45_write(bp, phy_addr, reg, addr, val);
 		msleep(5);
-		bnx2x_mdio45_read(bp, reg, addr, &rd_val);
+		bnx2x_mdio45_read(bp, phy_addr, reg, addr, &rd_val);
 		/* if the read value is not the same as the value we wrote,
 		   we should write it again */
 		if (rd_val == val)
@@ -1473,18 +1653,81 @@ static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val)
 }
 
 /*
- * link managment
+ * link management
  */
 
+static void bnx2x_pause_resolve(struct bnx2x *bp, u32 pause_result)
+{
+	switch (pause_result) {			/* ASYM P ASYM P */
+	case 0xb:				/*   1  0   1  1 */
+		bp->flow_ctrl = FLOW_CTRL_TX;
+		break;
+
+	case 0xe:				/*   1  1   1  0 */
+		bp->flow_ctrl = FLOW_CTRL_RX;
+		break;
+
+	case 0x5:				/*   0  1   0  1 */
+	case 0x7:				/*   0  1   1  1 */
+	case 0xd:				/*   1  1   0  1 */
+	case 0xf:				/*   1  1   1  1 */
+		bp->flow_ctrl = FLOW_CTRL_BOTH;
+		break;
+
+	default:
+		break;
+	}
+}
+
+static u8 bnx2x_ext_phy_resove_fc(struct bnx2x *bp)
+{
+	u32 ext_phy_addr;
+	u32 ld_pause;	/* local */
+	u32 lp_pause;	/* link partner */
+	u32 an_complete; /* AN complete */
+	u32 pause_result;
+	u8 ret = 0;
+
+	ext_phy_addr = ((bp->ext_phy_config &
+			 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+					PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+
+	/* read twice */
+	bnx2x_mdio45_read(bp, ext_phy_addr,
+			  EXT_PHY_KR_AUTO_NEG_DEVAD,
+			  EXT_PHY_KR_STATUS, &an_complete);
+	bnx2x_mdio45_read(bp, ext_phy_addr,
+			  EXT_PHY_KR_AUTO_NEG_DEVAD,
+			  EXT_PHY_KR_STATUS, &an_complete);
+
+	if (an_complete & EXT_PHY_KR_AUTO_NEG_COMPLETE) {
+		ret = 1;
+		bnx2x_mdio45_read(bp, ext_phy_addr,
+				  EXT_PHY_KR_AUTO_NEG_DEVAD,
+				  EXT_PHY_KR_AUTO_NEG_ADVERT, &ld_pause);
+		bnx2x_mdio45_read(bp, ext_phy_addr,
+				  EXT_PHY_KR_AUTO_NEG_DEVAD,
+				  EXT_PHY_KR_LP_AUTO_NEG, &lp_pause);
+		pause_result = (ld_pause &
+				EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK) >> 8;
+		pause_result |= (lp_pause &
+				 EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK) >> 10;
+		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
+		   pause_result);
+		bnx2x_pause_resolve(bp, pause_result);
+	}
+	return ret;
+}
+
 static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status)
 {
-	u32 ld_pause;   /* local driver */
-	u32 lp_pause;   /* link partner */
+	u32 ld_pause;	/* local driver */
+	u32 lp_pause;	/* link partner */
 	u32 pause_result;
 
 	bp->flow_ctrl = 0;
 
-	/* reolve from gp_status in case of AN complete and not sgmii */
+	/* resolve from gp_status in case of AN complete and not sgmii */
 	if ((bp->req_autoneg & AUTONEG_FLOW_CTRL) &&
 	    (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
 	    (!(bp->phy_flags & PHY_SGMII_FLAG)) &&
@@ -1501,45 +1744,57 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status)
 		pause_result |= (lp_pause &
 				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
 		DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
+		bnx2x_pause_resolve(bp, pause_result);
+	} else if (!(bp->req_autoneg & AUTONEG_FLOW_CTRL) ||
+		   !(bnx2x_ext_phy_resove_fc(bp))) {
+		/* forced speed */
+		if (bp->req_autoneg & AUTONEG_FLOW_CTRL) {
+			switch (bp->req_flow_ctrl) {
+			case FLOW_CTRL_AUTO:
+				if (bp->dev->mtu <= 4500)
+					bp->flow_ctrl = FLOW_CTRL_BOTH;
+				else
+					bp->flow_ctrl = FLOW_CTRL_TX;
+				break;
 
-		switch (pause_result) { 		/* ASYM P ASYM P */
-		case 0xb:       			/*   1  0   1  1 */
-			bp->flow_ctrl = FLOW_CTRL_TX;
-			break;
-
-		case 0xe:       			/*   1  1   1  0 */
-			bp->flow_ctrl = FLOW_CTRL_RX;
-			break;
+			case FLOW_CTRL_TX:
+				bp->flow_ctrl = FLOW_CTRL_TX;
+				break;
 
-		case 0x5:       			/*   0  1   0  1 */
-		case 0x7:       			/*   0  1   1  1 */
-		case 0xd:       			/*   1  1   0  1 */
-		case 0xf:       			/*   1  1   1  1 */
-			bp->flow_ctrl = FLOW_CTRL_BOTH;
-			break;
+			case FLOW_CTRL_RX:
+				if (bp->dev->mtu <= 4500)
+					bp->flow_ctrl = FLOW_CTRL_RX;
+				break;
 
-		default:
-			break;
-		}
+			case FLOW_CTRL_BOTH:
+				if (bp->dev->mtu <= 4500)
+					bp->flow_ctrl = FLOW_CTRL_BOTH;
+				else
+					bp->flow_ctrl = FLOW_CTRL_TX;
+				break;
 
-	} else { /* forced mode */
-		switch (bp->req_flow_ctrl) {
-		case FLOW_CTRL_AUTO:
-			if (bp->dev->mtu <= 4500)
-				bp->flow_ctrl = FLOW_CTRL_BOTH;
-			else
-				bp->flow_ctrl = FLOW_CTRL_TX;
-			break;
+			case FLOW_CTRL_NONE:
+			default:
+				break;
+			}
+		} else { /* forced mode */
+			switch (bp->req_flow_ctrl) {
+			case FLOW_CTRL_AUTO:
+				DP(NETIF_MSG_LINK, "req_flow_ctrl 0x%x while"
+						   " req_autoneg 0x%x\n",
+				   bp->req_flow_ctrl, bp->req_autoneg);
+				break;
 
-		case FLOW_CTRL_TX:
-		case FLOW_CTRL_RX:
-		case FLOW_CTRL_BOTH:
-			bp->flow_ctrl = bp->req_flow_ctrl;
-			break;
+			case FLOW_CTRL_TX:
+			case FLOW_CTRL_RX:
+			case FLOW_CTRL_BOTH:
+				bp->flow_ctrl = bp->req_flow_ctrl;
+				break;
 
-		case FLOW_CTRL_NONE:
-		default:
-			break;
+			case FLOW_CTRL_NONE:
+			default:
+				break;
+			}
 		}
 	}
 	DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", bp->flow_ctrl);
@@ -1550,9 +1805,9 @@ static void bnx2x_link_settings_status(struct bnx2x *bp, u32 gp_status)
 	bp->link_status = 0;
 
 	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
-		DP(NETIF_MSG_LINK, "link up\n");
+		DP(NETIF_MSG_LINK, "phy link up\n");
 
-		bp->link_up = 1;
+		bp->phy_link_up = 1;
 		bp->link_status |= LINK_STATUS_LINK_UP;
 
 		if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
@@ -1661,20 +1916,20 @@ static void bnx2x_link_settings_status(struct bnx2x *bp, u32 gp_status)
 		       bp->link_status |= LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
 
 	} else { /* link_down */
-		DP(NETIF_MSG_LINK, "link down\n");
+		DP(NETIF_MSG_LINK, "phy link down\n");
 
-		bp->link_up = 0;
+		bp->phy_link_up = 0;
 
 		bp->line_speed = 0;
 		bp->duplex = DUPLEX_FULL;
 		bp->flow_ctrl = 0;
 	}
 
-	DP(NETIF_MSG_LINK, "gp_status 0x%x  link_up %d\n"
+	DP(NETIF_MSG_LINK, "gp_status 0x%x  phy_link_up %d\n"
 	   DP_LEVEL "  line_speed %d  duplex %d  flow_ctrl 0x%x"
 		    "  link_status 0x%x\n",
-	   gp_status, bp->link_up, bp->line_speed, bp->duplex, bp->flow_ctrl,
-	   bp->link_status);
+	   gp_status, bp->phy_link_up, bp->line_speed, bp->duplex,
+	   bp->flow_ctrl, bp->link_status);
 }
 
 static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g)
@@ -1682,40 +1937,40 @@ static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g)
 	int port = bp->port;
 
 	/* first reset all status
-	 * we asume only one line will be change at a time */
+	 * we assume only one line will be change at a time */
 	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-		       (NIG_XGXS0_LINK_STATUS |
-			NIG_SERDES0_LINK_STATUS |
-			NIG_STATUS_INTERRUPT_XGXS0_LINK10G));
-	if (bp->link_up) {
+		       (NIG_STATUS_XGXS0_LINK10G |
+			NIG_STATUS_XGXS0_LINK_STATUS |
+			NIG_STATUS_SERDES0_LINK_STATUS));
+	if (bp->phy_link_up) {
 		if (is_10g) {
 			/* Disable the 10G link interrupt
 			 * by writing 1 to the status register
 			 */
-			DP(NETIF_MSG_LINK, "10G XGXS link up\n");
+			DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
 			bnx2x_bits_en(bp,
 				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-				      NIG_STATUS_INTERRUPT_XGXS0_LINK10G);
+				      NIG_STATUS_XGXS0_LINK10G);
 
 		} else if (bp->phy_flags & PHY_XGXS_FLAG) {
 			/* Disable the link interrupt
 			 * by writing 1 to the relevant lane
 			 * in the status register
 			 */
-			DP(NETIF_MSG_LINK, "1G XGXS link up\n");
+			DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
 			bnx2x_bits_en(bp,
 				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
 				      ((1 << bp->ser_lane) <<
-				       NIG_XGXS0_LINK_STATUS_SIZE));
+				       NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
 
 		} else { /* SerDes */
-			DP(NETIF_MSG_LINK, "SerDes link up\n");
+			DP(NETIF_MSG_LINK, "SerDes phy link up\n");
 			/* Disable the link interrupt
 			 * by writing 1 to the status register
 			 */
 			bnx2x_bits_en(bp,
 				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-				      NIG_SERDES0_LINK_STATUS);
+				      NIG_STATUS_SERDES0_LINK_STATUS);
 		}
 
 	} else { /* link_down */
@@ -1726,91 +1981,182 @@ static int bnx2x_ext_phy_is_link_up(struct bnx2x *bp)
 {
 	u32 ext_phy_type;
 	u32 ext_phy_addr;
-	u32 local_phy;
-	u32 val = 0;
+	u32 val1 = 0, val2;
 	u32 rx_sd, pcs_status;
 
 	if (bp->phy_flags & PHY_XGXS_FLAG) {
-		local_phy = bp->phy_addr;
 		ext_phy_addr = ((bp->ext_phy_config &
 				 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
 				PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
-		bp->phy_addr = (u8)ext_phy_addr;
 
 		ext_phy_type = XGXS_EXT_PHY_TYPE(bp);
 		switch (ext_phy_type) {
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
 			DP(NETIF_MSG_LINK, "XGXS Direct\n");
-			val = 1;
+			val1 = 1;
 			break;
 
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
 			DP(NETIF_MSG_LINK, "XGXS 8705\n");
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_WIS_DEVAD,
-					  EXT_PHY_OPT_LASI_STATUS, &val);
-			DP(NETIF_MSG_LINK, "8705 LASI status is %d\n", val);
-
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_WIS_DEVAD,
-					  EXT_PHY_OPT_LASI_STATUS, &val);
-			DP(NETIF_MSG_LINK, "8705 LASI status is %d\n", val);
-
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_WIS_DEVAD,
+					  EXT_PHY_OPT_LASI_STATUS, &val1);
+			DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
+
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_WIS_DEVAD,
+					  EXT_PHY_OPT_LASI_STATUS, &val1);
+			DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
+
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
 					  EXT_PHY_OPT_PMD_RX_SD, &rx_sd);
-			val = (rx_sd & 0x1);
+			DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
+			val1 = (rx_sd & 0x1);
 			break;
 
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
 			DP(NETIF_MSG_LINK, "XGXS 8706\n");
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
-					  EXT_PHY_OPT_LASI_STATUS, &val);
-			DP(NETIF_MSG_LINK, "8706 LASI status is %d\n", val);
-
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
-					  EXT_PHY_OPT_LASI_STATUS, &val);
-			DP(NETIF_MSG_LINK, "8706 LASI status is %d\n", val);
-
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_OPT_LASI_STATUS, &val1);
+			DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
+
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_OPT_LASI_STATUS, &val1);
+			DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
+
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
 					  EXT_PHY_OPT_PMD_RX_SD, &rx_sd);
-			bnx2x_mdio45_read(bp, EXT_PHY_OPT_PCS_DEVAD,
-					 EXT_PHY_OPT_PCS_STATUS, &pcs_status);
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PCS_DEVAD,
+					  EXT_PHY_OPT_PCS_STATUS, &pcs_status);
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_AUTO_NEG_DEVAD,
+					  EXT_PHY_OPT_AN_LINK_STATUS, &val2);
+
 			DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
-			   "  pcs_status 0x%x\n", rx_sd, pcs_status);
-			/* link is up if both bit 0 of pmd_rx and
-			 * bit 0 of pcs_status are set
+			   "  pcs_status 0x%x 1Gbps link_status 0x%x 0x%x\n",
+			   rx_sd, pcs_status, val2, (val2 & (1<<1)));
+			/* link is up if both bit 0 of pmd_rx_sd and
+			 * bit 0 of pcs_status are set, or if the autoneg bit
+			   1 is set
 			 */
-			val = (rx_sd & pcs_status);
+			val1 = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+			bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+
+			/* clear the interrupt LASI status register */
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					       ext_phy_addr,
+					       EXT_PHY_KR_PCS_DEVAD,
+					       EXT_PHY_KR_LASI_STATUS, &val2);
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					       ext_phy_addr,
+					       EXT_PHY_KR_PCS_DEVAD,
+					       EXT_PHY_KR_LASI_STATUS, &val1);
+			DP(NETIF_MSG_LINK, "KR LASI status 0x%x->0x%x\n",
+			   val2, val1);
+			/* Check the LASI */
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					       ext_phy_addr,
+					       EXT_PHY_KR_PMA_PMD_DEVAD,
+					       0x9003, &val2);
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					       ext_phy_addr,
+					       EXT_PHY_KR_PMA_PMD_DEVAD,
+					       0x9003, &val1);
+			DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n",
+			   val2, val1);
+			/* Check the link status */
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					       ext_phy_addr,
+					       EXT_PHY_KR_PCS_DEVAD,
+					       EXT_PHY_KR_PCS_STATUS, &val2);
+			DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
+			/* Check the link status on 1.1.2 */
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					  ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_KR_STATUS, &val2);
+			bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+					  ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_KR_STATUS, &val1);
+			DP(NETIF_MSG_LINK,
+			   "KR PMA status 0x%x->0x%x\n", val2, val1);
+			val1 = ((val1 & 4) == 4);
+			/* If 1G was requested assume the link is up */
+			if (!(bp->req_autoneg & AUTONEG_SPEED) &&
+			    (bp->req_line_speed == SPEED_1000))
+				val1 = 1;
+			bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_OPT_LASI_STATUS, &val2);
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_OPT_LASI_STATUS, &val1);
+			DP(NETIF_MSG_LINK,
+			   "10G-base-T LASI status 0x%x->0x%x\n", val2, val1);
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_KR_STATUS, &val2);
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_OPT_PMA_PMD_DEVAD,
+					  EXT_PHY_KR_STATUS, &val1);
+			DP(NETIF_MSG_LINK,
+			   "10G-base-T PMA status 0x%x->0x%x\n", val2, val1);
+			val1 = ((val1 & 4) == 4);
+			/* if link is up
+			 * print the AN outcome of the SFX7101 PHY
+			 */
+			if (val1) {
+				bnx2x_mdio45_read(bp, ext_phy_addr,
+						  EXT_PHY_KR_AUTO_NEG_DEVAD,
+						  0x21, &val2);
+				DP(NETIF_MSG_LINK,
+				   "SFX7101 AN status 0x%x->%s\n", val2,
+				   (val2 & (1<<14)) ? "Master" : "Slave");
+			}
 			break;
 
 		default:
 			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
 			   bp->ext_phy_config);
-			val = 0;
+			val1 = 0;
 			break;
 		}
-		bp->phy_addr = local_phy;
 
 	} else { /* SerDes */
 		ext_phy_type = SERDES_EXT_PHY_TYPE(bp);
 		switch (ext_phy_type) {
 		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
 			DP(NETIF_MSG_LINK, "SerDes Direct\n");
-			val = 1;
+			val1 = 1;
 			break;
 
 		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
 			DP(NETIF_MSG_LINK, "SerDes 5482\n");
-			val = 1;
+			val1 = 1;
 			break;
 
 		default:
 			DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
 			   bp->ext_phy_config);
-			val = 0;
+			val1 = 0;
 			break;
 		}
 	}
 
-	return val;
+	return val1;
 }
 
 static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb)
@@ -1821,7 +2167,7 @@ static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb)
 	u32 wb_write[2];
 	u32 val;
 
-	DP(NETIF_MSG_LINK, "enableing BigMAC\n");
+	DP(NETIF_MSG_LINK, "enabling BigMAC\n");
 	/* reset and unreset the BigMac */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
 	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
@@ -1935,6 +2281,35 @@ static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb)
 	bp->stats_state = STATS_STATE_ENABLE;
 }
 
+static void bnx2x_bmac_rx_disable(struct bnx2x *bp)
+{
+	int port = bp->port;
+	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
+			       NIG_REG_INGRESS_BMAC0_MEM;
+	u32 wb_write[2];
+
+	/* Only if the bmac is out of reset */
+	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+			(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)) {
+		/* Clear Rx Enable bit in BMAC_CONTROL register */
+#ifdef BNX2X_DMAE_RD
+		bnx2x_read_dmae(bp, bmac_addr +
+				BIGMAC_REGISTER_BMAC_CONTROL, 2);
+		wb_write[0] = *bnx2x_sp(bp, wb_data[0]);
+		wb_write[1] = *bnx2x_sp(bp, wb_data[1]);
+#else
+		wb_write[0] = REG_RD(bp,
+				bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL);
+		wb_write[1] = REG_RD(bp,
+				bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL + 4);
+#endif
+		wb_write[0] &= ~BMAC_CONTROL_RX_ENABLE;
+		REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
+			    wb_write, 2);
+		msleep(1);
+	}
+}
+
 static void bnx2x_emac_enable(struct bnx2x *bp)
 {
 	int port = bp->port;
@@ -1942,7 +2317,7 @@ static void bnx2x_emac_enable(struct bnx2x *bp)
 	u32 val;
 	int timeout;
 
-	DP(NETIF_MSG_LINK, "enableing EMAC\n");
+	DP(NETIF_MSG_LINK, "enabling EMAC\n");
 	/* reset and unreset the emac core */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
 	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
@@ -2035,7 +2410,7 @@ static void bnx2x_emac_enable(struct bnx2x *bp)
 				      EMAC_TX_MODE_EXT_PAUSE_EN);
 	}
 
-	/* KEEP_VLAN_TAG, promiscous */
+	/* KEEP_VLAN_TAG, promiscuous */
 	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
 	val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
 	EMAC_WR(EMAC_REG_EMAC_RX_MODE, val);
@@ -2163,7 +2538,6 @@ static void bnx2x_pbf_update(struct bnx2x *bp)
 	u32 count = 1000;
 	u32 pause = 0;
 
-
 	/* disable port */
 	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
 
@@ -2234,7 +2608,7 @@ static void bnx2x_pbf_update(struct bnx2x *bp)
 static void bnx2x_update_mng(struct bnx2x *bp)
 {
 	if (!nomcp)
-		SHMEM_WR(bp, drv_fw_mb[bp->port].link_status,
+		SHMEM_WR(bp, port_mb[bp->port].link_status,
 			 bp->link_status);
 }
 
@@ -2296,19 +2670,19 @@ static void bnx2x_link_down(struct bnx2x *bp)
 		DP(BNX2X_MSG_STATS, "stats_state - STOP\n");
 	}
 
-	/* indicate link down */
+	/* indicate no mac active */
 	bp->phy_flags &= ~(PHY_BMAC_FLAG | PHY_EMAC_FLAG);
 
-	/* reset BigMac */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	/* update shared memory */
+	bnx2x_update_mng(bp);
 
-	/* ignore drain flag interrupt */
 	/* activate nig drain */
 	NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
 
-	/* update shared memory */
-	bnx2x_update_mng(bp);
+	/* reset BigMac */
+	bnx2x_bmac_rx_disable(bp);
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 
 	/* indicate link down */
 	bnx2x_link_report(bp);
@@ -2319,14 +2693,15 @@ static void bnx2x_init_mac_stats(struct bnx2x *bp);
 /* This function is called upon link interrupt */
 static void bnx2x_link_update(struct bnx2x *bp)
 {
-	u32 gp_status;
 	int port = bp->port;
 	int i;
+	u32 gp_status;
 	int link_10g;
 
-	DP(NETIF_MSG_LINK, "port %x, is xgxs %x, stat_mask 0x%x,"
+	DP(NETIF_MSG_LINK, "port %x, %s, int_status 0x%x,"
 	   " int_mask 0x%x, saved_mask 0x%x, MI_INT %x, SERDES_LINK %x,"
-	   " 10G %x, XGXS_LINK %x\n", port, (bp->phy_flags & PHY_XGXS_FLAG),
+	   " 10G %x, XGXS_LINK %x\n", port,
+	   (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes",
 	   REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4),
 	   REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), bp->nig_mask,
 	   REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
@@ -2338,7 +2713,7 @@ static void bnx2x_link_update(struct bnx2x *bp)
 	might_sleep();
 	MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_GP_STATUS);
 	/* avoid fast toggling */
-	for (i = 0 ; i < 10 ; i++) {
+	for (i = 0; i < 10; i++) {
 		msleep(10);
 		bnx2x_mdio22_read(bp, MDIO_GP_STATUS_TOP_AN_STATUS1,
 				  &gp_status);
@@ -2353,7 +2728,8 @@ static void bnx2x_link_update(struct bnx2x *bp)
 	bnx2x_link_int_ack(bp, link_10g);
 
 	/* link is up only if both local phy and external phy are up */
-	if (bp->link_up && bnx2x_ext_phy_is_link_up(bp)) {
+	bp->link_up = (bp->phy_link_up && bnx2x_ext_phy_is_link_up(bp));
+	if (bp->link_up) {
 		if (link_10g) {
 			bnx2x_bmac_enable(bp, 0);
 			bnx2x_leds_set(bp, SPEED_10000);
@@ -2429,7 +2805,9 @@ static void bnx2x_reset_unicore(struct bnx2x *bp)
 		}
 	}
 
-	BNX2X_ERR("BUG! unicore is still in reset!\n");
+	BNX2X_ERR("BUG! %s (0x%x) is still in reset!\n",
+		  (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes",
+		  bp->phy_addr);
 }
 
 static void bnx2x_set_swap_lanes(struct bnx2x *bp)
@@ -2477,12 +2855,12 @@ static void bnx2x_set_parallel_detection(struct bnx2x *bp)
 		MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_10G_PARALLEL_DETECT);
 
 		bnx2x_mdio22_write(bp,
-				   MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
+				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
 			       MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
 
 		bnx2x_mdio22_read(bp,
-				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
-				  &control2);
+				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
+				&control2);
 
 		if (bp->autoneg & AUTONEG_PARALLEL) {
 			control2 |=
@@ -2492,8 +2870,14 @@ static void bnx2x_set_parallel_detection(struct bnx2x *bp)
 		   ~MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
 		}
 		bnx2x_mdio22_write(bp,
-				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
-				   control2);
+				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
+				control2);
+
+		/* Disable parallel detection of HiG */
+		MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_XGXS_BLOCK2);
+		bnx2x_mdio22_write(bp, MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
+				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
+				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
 	}
 }
 
@@ -2627,7 +3011,7 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x *bp)
 	MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_OVER_1G);
 
 	/* set extended capabilities */
-	if (bp->advertising & ADVERTISED_2500baseT_Full)
+	if (bp->advertising & ADVERTISED_2500baseX_Full)
 		val |= MDIO_OVER_1G_UP1_2_5G;
 	if (bp->advertising & ADVERTISED_10000baseT_Full)
 		val |= MDIO_OVER_1G_UP1_10G;
@@ -2643,20 +3027,91 @@ static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x *bp)
 	/* for AN, we are always publishing full duplex */
 	an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
 
-	/* set pause */
-	switch (bp->pause_mode) {
-	case PAUSE_SYMMETRIC:
-		an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
-		break;
-	case PAUSE_ASYMMETRIC:
-		an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		break;
-	case PAUSE_BOTH:
-		an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-		break;
-	case PAUSE_NONE:
-		an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
-		break;
+	/* resolve pause mode and advertisement
+	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
+	if (bp->req_autoneg & AUTONEG_FLOW_CTRL) {
+		switch (bp->req_flow_ctrl) {
+		case FLOW_CTRL_AUTO:
+			if (bp->dev->mtu <= 4500) {
+				an_adv |=
+				     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+				bp->advertising |= (ADVERTISED_Pause |
+						    ADVERTISED_Asym_Pause);
+			} else {
+				an_adv |=
+			       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+				bp->advertising |= ADVERTISED_Asym_Pause;
+			}
+			break;
+
+		case FLOW_CTRL_TX:
+			an_adv |=
+			       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+			bp->advertising |= ADVERTISED_Asym_Pause;
+			break;
+
+		case FLOW_CTRL_RX:
+			if (bp->dev->mtu <= 4500) {
+				an_adv |=
+				     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+				bp->advertising |= (ADVERTISED_Pause |
+						    ADVERTISED_Asym_Pause);
+			} else {
+				an_adv |=
+				     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+				bp->advertising &= ~(ADVERTISED_Pause |
+						     ADVERTISED_Asym_Pause);
+			}
+			break;
+
+		case FLOW_CTRL_BOTH:
+			if (bp->dev->mtu <= 4500) {
+				an_adv |=
+				     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+				bp->advertising |= (ADVERTISED_Pause |
+						    ADVERTISED_Asym_Pause);
+			} else {
+				an_adv |=
+			       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+				bp->advertising |= ADVERTISED_Asym_Pause;
+			}
+			break;
+
+		case FLOW_CTRL_NONE:
+		default:
+			an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+			bp->advertising &= ~(ADVERTISED_Pause |
+					     ADVERTISED_Asym_Pause);
+			break;
+		}
+	} else { /* forced mode */
+		switch (bp->req_flow_ctrl) {
+		case FLOW_CTRL_AUTO:
+			DP(NETIF_MSG_LINK, "req_flow_ctrl 0x%x while"
+					   " req_autoneg 0x%x\n",
+			   bp->req_flow_ctrl, bp->req_autoneg);
+			break;
+
+		case FLOW_CTRL_TX:
+			an_adv |=
+			       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+			bp->advertising |= ADVERTISED_Asym_Pause;
+			break;
+
+		case FLOW_CTRL_RX:
+		case FLOW_CTRL_BOTH:
+			an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+			bp->advertising |= (ADVERTISED_Pause |
+					    ADVERTISED_Asym_Pause);
+			break;
+
+		case FLOW_CTRL_NONE:
+		default:
+			an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+			bp->advertising &= ~(ADVERTISED_Pause |
+					     ADVERTISED_Asym_Pause);
+			break;
+		}
 	}
 
 	MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_COMBO_IEEE0);
@@ -2754,47 +3209,162 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x *bp)
 static void bnx2x_link_int_enable(struct bnx2x *bp)
 {
 	int port = bp->port;
+	u32 ext_phy_type;
+	u32 mask;
 
 	/* setting the status to report on link up
 	   for either XGXS or SerDes */
 	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-		       (NIG_XGXS0_LINK_STATUS |
-			NIG_STATUS_INTERRUPT_XGXS0_LINK10G |
-			NIG_SERDES0_LINK_STATUS));
+		       (NIG_STATUS_XGXS0_LINK10G |
+			NIG_STATUS_XGXS0_LINK_STATUS |
+			NIG_STATUS_SERDES0_LINK_STATUS));
 
 	if (bp->phy_flags & PHY_XGXS_FLAG) {
-		/* TBD -
-		 * in force mode (not AN) we can enable just the relevant
-		 * interrupt
-		 * Even in AN we might enable only one according to the AN
-		 * speed mask
-		 */
-		bnx2x_bits_en(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-			      (NIG_MASK_XGXS0_LINK_STATUS |
-			       NIG_MASK_XGXS0_LINK10G));
-		DP(NETIF_MSG_LINK, "enable XGXS interrupt\n");
+		mask = (NIG_MASK_XGXS0_LINK10G |
+			NIG_MASK_XGXS0_LINK_STATUS);
+		DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
+		ext_phy_type = XGXS_EXT_PHY_TYPE(bp);
+		if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
+		    (ext_phy_type !=
+				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
+			mask |= NIG_MASK_MI_INT;
+			DP(NETIF_MSG_LINK, "enabled external phy int\n");
+		}
 
 	} else { /* SerDes */
-		bnx2x_bits_en(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-			      NIG_MASK_SERDES0_LINK_STATUS);
-		DP(NETIF_MSG_LINK, "enable SerDes interrupt\n");
+		mask = NIG_MASK_SERDES0_LINK_STATUS;
+		DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
+		ext_phy_type = SERDES_EXT_PHY_TYPE(bp);
+		if ((ext_phy_type !=
+				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
+		    (ext_phy_type !=
+				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
+			mask |= NIG_MASK_MI_INT;
+			DP(NETIF_MSG_LINK, "enabled external phy int\n");
+		}
 	}
+	bnx2x_bits_en(bp,
+		      NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
+		      mask);
+	DP(NETIF_MSG_LINK, "port %x, %s, int_status 0x%x,"
+	   " int_mask 0x%x, MI_INT %x, SERDES_LINK %x,"
+	   " 10G %x, XGXS_LINK %x\n", port,
+	   (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes",
+	   REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4),
+	   REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
+	   REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
+	   REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c),
+	   REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
+	   REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)
+	);
+}
+
+static void bnx2x_bcm8072_external_rom_boot(struct bnx2x *bp)
+{
+	u32 ext_phy_addr = ((bp->ext_phy_config &
+			     PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+			    PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+	u32 fw_ver1, fw_ver2;
+
+	/* Need to wait 200ms after reset */
+	msleep(200);
+	/* Boot port from external ROM
+	 * Set ser_boot_ctl bit in the MISC_CTRL1 register
+	 */
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD,
+				EXT_PHY_KR_MISC_CTRL1, 0x0001);
+
+	/* Reset internal microprocessor */
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL,
+				EXT_PHY_KR_ROM_RESET_INTERNAL_MP);
+	/* set micro reset = 0 */
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL,
+				EXT_PHY_KR_ROM_MICRO_RESET);
+	/* Reset internal microprocessor */
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL,
+				EXT_PHY_KR_ROM_RESET_INTERNAL_MP);
+	/* wait for 100ms for code download via SPI port */
+	msleep(100);
+
+	/* Clear ser_boot_ctl bit */
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD,
+				EXT_PHY_KR_MISC_CTRL1, 0x0000);
+	/* Wait 100ms */
+	msleep(100);
+
+	/* Print the PHY FW version */
+	bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, ext_phy_addr,
+			       EXT_PHY_KR_PMA_PMD_DEVAD,
+			       0xca19, &fw_ver1);
+	bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, ext_phy_addr,
+			       EXT_PHY_KR_PMA_PMD_DEVAD,
+			       0xca1a, &fw_ver2);
+	DP(NETIF_MSG_LINK,
+	   "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
+}
+
+static void bnx2x_bcm8072_force_10G(struct bnx2x *bp)
+{
+	u32 ext_phy_addr = ((bp->ext_phy_config &
+			     PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+			    PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+
+	/* Force KR or KX */
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_CTRL,
+				0x2040);
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_CTRL2,
+				0x000b);
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_PMD_CTRL,
+				0x0000);
+	bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr,
+				EXT_PHY_KR_AUTO_NEG_DEVAD, EXT_PHY_KR_CTRL,
+				0x0000);
 }
 
 static void bnx2x_ext_phy_init(struct bnx2x *bp)
 {
-	int port = bp->port;
 	u32 ext_phy_type;
 	u32 ext_phy_addr;
-	u32 local_phy;
+	u32 cnt;
+	u32 ctrl;
+	u32 val = 0;
 
 	if (bp->phy_flags & PHY_XGXS_FLAG) {
-		local_phy = bp->phy_addr;
 		ext_phy_addr = ((bp->ext_phy_config &
 				 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
 				PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
 
 		ext_phy_type = XGXS_EXT_PHY_TYPE(bp);
+		/* Make sure that the soft reset is off (expect for the 8072:
+		 * due to the lock, it will be done inside the specific
+		 * handling)
+		 */
+		if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
+		   (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
+		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)) {
+			/* Wait for soft reset to get cleared upto 1 sec */
+			for (cnt = 0; cnt < 1000; cnt++) {
+				bnx2x_mdio45_read(bp, ext_phy_addr,
+						  EXT_PHY_OPT_PMA_PMD_DEVAD,
+						  EXT_PHY_OPT_CNTL, &ctrl);
+				if (!(ctrl & (1<<15)))
+					break;
+				msleep(1);
+			}
+			DP(NETIF_MSG_LINK,
+			   "control reg 0x%x (after %d ms)\n", ctrl, cnt);
+		}
+
 		switch (ext_phy_type) {
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
 			DP(NETIF_MSG_LINK, "XGXS Direct\n");
@@ -2802,49 +3372,235 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp)
 
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
 			DP(NETIF_MSG_LINK, "XGXS 8705\n");
-			bnx2x_bits_en(bp,
-				      NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-				      NIG_MASK_MI_INT);
-			DP(NETIF_MSG_LINK, "enabled extenal phy int\n");
 
-			bp->phy_addr = ext_phy_type;
-			bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_OPT_PMA_PMD_DEVAD,
 					    EXT_PHY_OPT_PMD_MISC_CNTL,
 					    0x8288);
-			bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_OPT_PMA_PMD_DEVAD,
 					    EXT_PHY_OPT_PHY_IDENTIFIER,
 					    0x7fbf);
-			bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_OPT_PMA_PMD_DEVAD,
 					    EXT_PHY_OPT_CMU_PLL_BYPASS,
 					    0x0100);
-			bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_WIS_DEVAD,
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_OPT_WIS_DEVAD,
 					    EXT_PHY_OPT_LASI_CNTL, 0x1);
 			break;
 
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
 			DP(NETIF_MSG_LINK, "XGXS 8706\n");
-			bnx2x_bits_en(bp,
-				      NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-				      NIG_MASK_MI_INT);
-			DP(NETIF_MSG_LINK, "enabled extenal phy int\n");
-
-			bp->phy_addr = ext_phy_type;
-			bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
-					    EXT_PHY_OPT_PMD_DIGITAL_CNT,
-					    0x400);
-			bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+
+			if (!(bp->req_autoneg & AUTONEG_SPEED)) {
+				/* Force speed */
+				if (bp->req_line_speed == SPEED_10000) {
+					DP(NETIF_MSG_LINK,
+					   "XGXS 8706 force 10Gbps\n");
+					bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						EXT_PHY_OPT_PMA_PMD_DEVAD,
+						EXT_PHY_OPT_PMD_DIGITAL_CNT,
+						0x400);
+				} else {
+					/* Force 1Gbps */
+					DP(NETIF_MSG_LINK,
+					   "XGXS 8706 force 1Gbps\n");
+
+					bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						EXT_PHY_OPT_PMA_PMD_DEVAD,
+						EXT_PHY_OPT_CNTL,
+						0x0040);
+
+					bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						EXT_PHY_OPT_PMA_PMD_DEVAD,
+						EXT_PHY_OPT_CNTL2,
+						0x000D);
+				}
+
+				/* Enable LASI */
+				bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						    EXT_PHY_OPT_PMA_PMD_DEVAD,
+						    EXT_PHY_OPT_LASI_CNTL,
+						    0x1);
+			} else {
+				/* AUTONEG */
+				/* Allow CL37 through CL73 */
+				DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
+				bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						    EXT_PHY_AUTO_NEG_DEVAD,
+						    EXT_PHY_OPT_AN_CL37_CL73,
+						    0x040c);
+
+				/* Enable Full-Duplex advertisment on CL37 */
+				bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						    EXT_PHY_AUTO_NEG_DEVAD,
+						    EXT_PHY_OPT_AN_CL37_FD,
+						    0x0020);
+				/* Enable CL37 AN */
+				bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						    EXT_PHY_AUTO_NEG_DEVAD,
+						    EXT_PHY_OPT_AN_CL37_AN,
+						    0x1000);
+				/* Advertise 10G/1G support */
+				if (bp->advertising &
+				    ADVERTISED_1000baseT_Full)
+					val = (1<<5);
+				if (bp->advertising &
+				    ADVERTISED_10000baseT_Full)
+					val |= (1<<7);
+
+				bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						    EXT_PHY_AUTO_NEG_DEVAD,
+						    EXT_PHY_OPT_AN_ADV, val);
+				/* Enable LASI */
+				bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+						    EXT_PHY_OPT_PMA_PMD_DEVAD,
+						    EXT_PHY_OPT_LASI_CNTL,
+						    0x1);
+
+				/* Enable clause 73 AN */
+				bnx2x_mdio45_write(bp, ext_phy_addr,
+						   EXT_PHY_AUTO_NEG_DEVAD,
+						   EXT_PHY_OPT_CNTL,
+						   0x1200);
+			}
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+			bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+			/* Wait for soft reset to get cleared upto 1 sec */
+			for (cnt = 0; cnt < 1000; cnt++) {
+				bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_OPT_PMA_PMD_DEVAD,
+						EXT_PHY_OPT_CNTL, &ctrl);
+				if (!(ctrl & (1<<15)))
+					break;
+				msleep(1);
+			}
+			DP(NETIF_MSG_LINK,
+			   "8072 control reg 0x%x (after %d ms)\n",
+			   ctrl, cnt);
+
+			bnx2x_bcm8072_external_rom_boot(bp);
+			DP(NETIF_MSG_LINK, "Finshed loading 8072 KR ROM\n");
+
+			/* enable LASI */
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_KR_PMA_PMD_DEVAD,
+						0x9000, 0x0400);
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_KR_PMA_PMD_DEVAD,
+						EXT_PHY_KR_LASI_CNTL, 0x0004);
+
+			/* If this is forced speed, set to KR or KX
+			 * (all other are not supported)
+			 */
+			if (!(bp->req_autoneg & AUTONEG_SPEED)) {
+				if (bp->req_line_speed == SPEED_10000) {
+					bnx2x_bcm8072_force_10G(bp);
+					DP(NETIF_MSG_LINK,
+					   "Forced speed 10G on 8072\n");
+					/* unlock */
+					bnx2x_hw_unlock(bp,
+						HW_LOCK_RESOURCE_8072_MDIO);
+					break;
+				} else
+					val = (1<<5);
+			} else {
+
+				/* Advertise 10G/1G support */
+				if (bp->advertising &
+						ADVERTISED_1000baseT_Full)
+					val = (1<<5);
+				if (bp->advertising &
+						ADVERTISED_10000baseT_Full)
+					val |= (1<<7);
+			}
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+					ext_phy_addr,
+					EXT_PHY_KR_AUTO_NEG_DEVAD,
+					0x11, val);
+			/* Add support for CL37 ( passive mode ) I */
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_KR_AUTO_NEG_DEVAD,
+						0x8370, 0x040c);
+			/* Add support for CL37 ( passive mode ) II */
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_KR_AUTO_NEG_DEVAD,
+						0xffe4, 0x20);
+			/* Add support for CL37 ( passive mode ) III */
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_KR_AUTO_NEG_DEVAD,
+						0xffe0, 0x1000);
+			/* Restart autoneg */
+			msleep(500);
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+					ext_phy_addr,
+					EXT_PHY_KR_AUTO_NEG_DEVAD,
+					EXT_PHY_KR_CTRL, 0x1200);
+			DP(NETIF_MSG_LINK, "8072 Autoneg Restart: "
+			   "1G %ssupported  10G %ssupported\n",
+			   (val & (1<<5)) ? "" : "not ",
+			   (val & (1<<7)) ? "" : "not ");
+
+			/* unlock */
+			bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+			DP(NETIF_MSG_LINK,
+			   "Setting the SFX7101 LASI indication\n");
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_OPT_PMA_PMD_DEVAD,
 					    EXT_PHY_OPT_LASI_CNTL, 0x1);
+			DP(NETIF_MSG_LINK,
+			   "Setting the SFX7101 LED to blink on traffic\n");
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_OPT_PMA_PMD_DEVAD,
+					    0xC007, (1<<3));
+
+			/* read modify write pause advertizing */
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_KR_AUTO_NEG_DEVAD,
+					  EXT_PHY_KR_AUTO_NEG_ADVERT, &val);
+			val &= ~EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_BOTH;
+			/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+			if (bp->advertising & ADVERTISED_Pause)
+				val |= EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE;
+
+			if (bp->advertising & ADVERTISED_Asym_Pause) {
+				val |=
+				 EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_ASYMMETRIC;
+			}
+			DP(NETIF_MSG_LINK, "SFX7101 AN advertize 0x%x\n", val);
+			bnx2x_mdio45_vwrite(bp, ext_phy_addr,
+					    EXT_PHY_KR_AUTO_NEG_DEVAD,
+					    EXT_PHY_KR_AUTO_NEG_ADVERT, val);
+			/* Restart autoneg */
+			bnx2x_mdio45_read(bp, ext_phy_addr,
+					  EXT_PHY_KR_AUTO_NEG_DEVAD,
+					  EXT_PHY_KR_CTRL, &val);
+			val |= 0x200;
+			bnx2x_mdio45_write(bp, ext_phy_addr,
+					    EXT_PHY_KR_AUTO_NEG_DEVAD,
+					    EXT_PHY_KR_CTRL, val);
 			break;
 
 		default:
-			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
-			   bp->ext_phy_config);
+			BNX2X_ERR("BAD XGXS ext_phy_config 0x%x\n",
+				  bp->ext_phy_config);
 			break;
 		}
-		bp->phy_addr = local_phy;
 
 	} else { /* SerDes */
-/*      	ext_phy_addr = ((bp->ext_phy_config &
+/*		ext_phy_addr = ((bp->ext_phy_config &
 				 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >>
 				PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT);
 */
@@ -2856,10 +3612,6 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp)
 
 		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
 			DP(NETIF_MSG_LINK, "SerDes 5482\n");
-			bnx2x_bits_en(bp,
-				      NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-				      NIG_MASK_MI_INT);
-			DP(NETIF_MSG_LINK, "enabled extenal phy int\n");
 			break;
 
 		default:
@@ -2873,8 +3625,22 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp)
 static void bnx2x_ext_phy_reset(struct bnx2x *bp)
 {
 	u32 ext_phy_type;
-	u32 ext_phy_addr;
-	u32 local_phy;
+	u32 ext_phy_addr = ((bp->ext_phy_config &
+			     PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+			    PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+	u32 board = (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK);
+
+	/* The PHY reset is controled by GPIO 1
+	 * Give it 1ms of reset pulse
+	 */
+	if ((board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1002G) &&
+	    (board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G)) {
+		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+			       MISC_REGISTERS_GPIO_OUTPUT_LOW);
+		msleep(1);
+		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+			       MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+	}
 
 	if (bp->phy_flags & PHY_XGXS_FLAG) {
 		ext_phy_type = XGXS_EXT_PHY_TYPE(bp);
@@ -2885,15 +3651,24 @@ static void bnx2x_ext_phy_reset(struct bnx2x *bp)
 
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-			DP(NETIF_MSG_LINK, "XGXS 8705/6\n");
-			local_phy = bp->phy_addr;
-			ext_phy_addr = ((bp->ext_phy_config &
-					PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
-					PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
-			bp->phy_addr = (u8)ext_phy_addr;
-			bnx2x_mdio45_write(bp, EXT_PHY_OPT_PMA_PMD_DEVAD,
+			DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
+			bnx2x_mdio45_write(bp, ext_phy_addr,
+					   EXT_PHY_OPT_PMA_PMD_DEVAD,
 					   EXT_PHY_OPT_CNTL, 0xa040);
-			bp->phy_addr = local_phy;
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+			DP(NETIF_MSG_LINK, "XGXS 8072\n");
+			bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+			bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0,
+						ext_phy_addr,
+						EXT_PHY_KR_PMA_PMD_DEVAD,
+						0, 1<<15);
+			bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+			DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
 			break;
 
 		default:
@@ -2932,6 +3707,7 @@ static void bnx2x_link_initialize(struct bnx2x *bp)
 			NIG_MASK_SERDES0_LINK_STATUS |
 			NIG_MASK_MI_INT));
 
+	/* Activate the external PHY */
 	bnx2x_ext_phy_reset(bp);
 
 	bnx2x_set_aer_mmd(bp);
@@ -2996,13 +3772,13 @@ static void bnx2x_link_initialize(struct bnx2x *bp)
 			/* AN enabled */
 			bnx2x_set_brcm_cl37_advertisment(bp);
 
-			/* program duplex & pause advertisment (for aneg) */
+			/* program duplex & pause advertisement (for aneg) */
 			bnx2x_set_ieee_aneg_advertisment(bp);
 
 			/* enable autoneg */
 			bnx2x_set_autoneg(bp);
 
-			/* enalbe and restart AN */
+			/* enable and restart AN */
 			bnx2x_restart_autoneg(bp);
 		}
 
@@ -3012,11 +3788,11 @@ static void bnx2x_link_initialize(struct bnx2x *bp)
 		bnx2x_initialize_sgmii_process(bp);
 	}
 
-	/* enable the interrupt */
-	bnx2x_link_int_enable(bp);
-
 	/* init ext phy and enable link state int */
 	bnx2x_ext_phy_init(bp);
+
+	/* enable the interrupt */
+	bnx2x_link_int_enable(bp);
 }
 
 static void bnx2x_phy_deassert(struct bnx2x *bp)
@@ -3075,6 +3851,11 @@ static int bnx2x_phy_init(struct bnx2x *bp)
 static void bnx2x_link_reset(struct bnx2x *bp)
 {
 	int port = bp->port;
+	u32 board = (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK);
+
+	/* update shared memory */
+	bp->link_status = 0;
+	bnx2x_update_mng(bp);
 
 	/* disable attentions */
 	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
@@ -3083,21 +3864,45 @@ static void bnx2x_link_reset(struct bnx2x *bp)
 			NIG_MASK_SERDES0_LINK_STATUS |
 			NIG_MASK_MI_INT));
 
-	bnx2x_ext_phy_reset(bp);
+	/* activate nig drain */
+	NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+
+	/* disable nig egress interface */
+	NIG_WR(NIG_REG_BMAC0_OUT_EN + port*4, 0);
+	NIG_WR(NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+
+	/* Stop BigMac rx */
+	bnx2x_bmac_rx_disable(bp);
+
+	/* disable emac */
+	NIG_WR(NIG_REG_NIG_EMAC0_EN + port*4, 0);
+
+	msleep(10);
+
+	/* The PHY reset is controled by GPIO 1
+	 * Hold it as output low
+	 */
+	if ((board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1002G) &&
+	    (board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G)) {
+		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+			       MISC_REGISTERS_GPIO_OUTPUT_LOW);
+		DP(NETIF_MSG_LINK, "reset external PHY\n");
+	}
 
 	/* reset the SerDes/XGXS */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
 	       (0x1ff << (port*16)));
 
-	/* reset EMAC / BMAC and disable NIG interfaces */
-	NIG_WR(NIG_REG_BMAC0_IN_EN + port*4, 0);
-	NIG_WR(NIG_REG_BMAC0_OUT_EN + port*4, 0);
+	/* reset BigMac */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 
-	NIG_WR(NIG_REG_NIG_EMAC0_EN + port*4, 0);
+	/* disable nig ingress interface */
+	NIG_WR(NIG_REG_BMAC0_IN_EN + port*4, 0);
 	NIG_WR(NIG_REG_EMAC0_IN_EN + port*4, 0);
-	NIG_WR(NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
 
-	NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+	/* set link down */
+	bp->link_up = 0;
 }
 
 #ifdef BNX2X_XGXS_LB
@@ -3160,7 +3965,7 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 	int port = bp->port;
 
 	DP(NETIF_MSG_TIMER,
-	   "spe (%x:%x)  command %x  hw_cid %x  data (%x:%x)  left %x\n",
+	   "spe (%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);
@@ -3178,6 +3983,7 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 		bnx2x_panic();
 		return -EBUSY;
 	}
+
 	/* CID needs port number to be encoded int it */
 	bp->spq_prod_bd->hdr.conn_and_cmd_data =
 			cpu_to_le32(((command << SPE_HDR_CMD_ID_SHIFT) |
@@ -3284,8 +4090,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");
@@ -3303,15 +4109,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? */
@@ -3364,15 +4166,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;
 
@@ -3393,64 +4312,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) ||
@@ -3458,7 +4327,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) ||
@@ -3466,7 +4343,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 atention\n");
+			       BNX2X_ERR("FATAL HW block parity attention\n");
 		}
 	}
 
@@ -3531,7 +4408,7 @@ static void bnx2x_sp_task(void *data)
 
 	/* 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;
 	}
 
@@ -3541,12 +4418,11 @@ static void bnx2x_sp_task(void *data)
 
 	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;
 
@@ -3571,11 +4447,11 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance, struct pt_regs
 
 	/* 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))
@@ -3910,7 +4786,7 @@ static void bnx2x_stop_stats(struct bnx2x *bp)
 
 		while (bp->stats_state != STATS_STATE_DISABLE) {
 			if (!timeout) {
-				BNX2X_ERR("timeout wating for stats stop\n");
+				BNX2X_ERR("timeout waiting for stats stop\n");
 				break;
 			}
 			timeout--;
@@ -4177,39 +5053,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;
@@ -4338,7 +5212,7 @@ static void bnx2x_timer(unsigned long data)
 		return;
 
 	if (atomic_read(&bp->intr_sem) != 0)
-		goto bnx2x_restart_timer;
+		goto timer_restart;
 
 	if (poll) {
 		struct bnx2x_fastpath *fp = &bp->fp[0];
@@ -4348,7 +5222,7 @@ static void bnx2x_timer(unsigned long data)
 		rc = bnx2x_rx_int(fp, 1000);
 	}
 
-	if (!nomcp && (bp->bc_ver >= 0x040003)) {
+	if (!nomcp) {
 		int port = bp->port;
 		u32 drv_pulse;
 		u32 mcp_pulse;
@@ -4357,9 +5231,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, drv_fw_mb[port].drv_pulse_mb, drv_pulse);
+		SHMEM_WR(bp, func_mb[port].drv_pulse_mb, drv_pulse);
 
-		mcp_pulse = (SHMEM_RD(bp, drv_fw_mb[port].mcp_pulse_mb) &
+		mcp_pulse = (SHMEM_RD(bp, func_mb[port].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)
@@ -4373,11 +5247,11 @@ static void bnx2x_timer(unsigned long data)
 	}
 
 	if (bp->stats_state == STATS_STATE_DISABLE)
-		goto bnx2x_restart_timer;
+		goto timer_restart;
 
 	bnx2x_update_stats(bp);
 
-bnx2x_restart_timer:
+timer_restart:
 	mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
@@ -4442,6 +5316,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);
 
@@ -4476,6 +5353,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 +
@@ -4493,6 +5372,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 +
@@ -4510,6 +5391,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 +
@@ -4527,6 +5410,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 +
@@ -4539,6 +5424,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);
 }
 
@@ -4630,7 +5517,7 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
 		fp->rx_bd_prod = fp->rx_comp_prod = ring_prod;
 		fp->rx_pkt = fp->rx_calls = 0;
 
-		/* Warning! this will genrate an interrupt (to the TSTORM) */
+		/* 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);
@@ -4682,7 +5569,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;
@@ -4759,6 +5645,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;
@@ -4798,41 +5720,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)
@@ -4840,7 +5730,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;
@@ -4854,13 +5743,9 @@ static void bnx2x_init_internal(struct bnx2x *bp)
 /*      DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n",
 	   (*(u32 *)&tstorm_config)); */
 
-	bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx untill link is up */
+	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),
@@ -4906,7 +5791,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);
 
 }
 
@@ -5269,8 +6154,10 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 	if (mode & 0x1) {       /* init common */
 		DP(BNX2X_MSG_MCP, "starting common init  func %d  mode %x\n",
 		   func, mode);
-		REG_WR(bp, MISC_REG_RESET_REG_1, 0xffffffff);
-		REG_WR(bp, MISC_REG_RESET_REG_2, 0xfffc);
+		REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
+		       0xffffffff);
+		REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
+		       0xfffc);
 		bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END);
 
 		REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
@@ -5363,7 +6250,7 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 		REG_RD(bp, USEM_REG_PASSIVE_BUFFER + 8);
 #endif
 		bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END);
-		/* softrest pulse */
+		/* soft reset pulse */
 		REG_WR(bp, QM_REG_SOFT_RESET, 1);
 		REG_WR(bp, QM_REG_SOFT_RESET, 0);
 
@@ -5417,7 +6304,7 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 		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: repleace with something meaningfull */
+			/* TODO: replace with something meaningful */
 		}
 		/* SRCH COMMON comes here */
 		REG_WR(bp, SRC_REG_SOFT_RST, 0);
@@ -5490,6 +6377,28 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 		enable_blocks_attention(bp);
 		/* enable_blocks_parity(bp); */
 
+		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);
+
+			/* 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);
+
+			/* 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;
+		}
+
 	} /* end of common init */
 
 	/* per port init */
@@ -5649,9 +6558,21 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 	/* Port MCP comes here */
 	/* Port DMAE comes here */
 
+	switch (bp->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);
+		val |= AEU_INPUTS_ATTN_BITS_SPIO5;
+		REG_WR(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, val);
+		break;
+
+	default:
+		break;
+	}
+
 	bnx2x_link_reset(bp);
 
-	/* Reset pciex errors for debug */
+	/* Reset PCIE errors for debug */
 	REG_WR(bp, 0x2114, 0xffffffff);
 	REG_WR(bp, 0x2120, 0xffffffff);
 	REG_WR(bp, 0x2814, 0xffffffff);
@@ -5673,9 +6594,9 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 		port = bp->port;
 
 		bp->fw_drv_pulse_wr_seq =
-				(SHMEM_RD(bp, drv_fw_mb[port].drv_pulse_mb) &
+				(SHMEM_RD(bp, func_mb[port].drv_pulse_mb) &
 				 DRV_PULSE_SEQ_MASK);
-		bp->fw_mb = SHMEM_RD(bp, drv_fw_mb[port].fw_mb_param);
+		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 {
@@ -5685,16 +6606,15 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 	return 0;
 }
 
-
-/* send the MCP a request, block untill there is a reply */
+/* send the MCP a request, block until there is a reply */
 static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
 {
-	u32 rc = 0;
-	u32 seq = ++bp->fw_seq;
 	int port = bp->port;
+	u32 seq = ++bp->fw_seq;
+	u32 rc = 0;
 
-	SHMEM_WR(bp, drv_fw_mb[port].drv_mb_header, command|seq);
-	DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", command|seq);
+	SHMEM_WR(bp, func_mb[port].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 ... */
 	msleep(100); /* TBD */
@@ -5702,19 +6622,20 @@ static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
 	if (CHIP_REV_IS_SLOW(bp))
 		msleep(900);
 
-	rc = SHMEM_RD(bp, drv_fw_mb[port].fw_mb_header);
-
+	rc = SHMEM_RD(bp, func_mb[port].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? */
 	if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) {
 		rc &= FW_MSG_CODE_MASK;
+
 	} else {
 		/* FW BUG! */
 		BNX2X_ERR("FW failed to respond!\n");
 		bnx2x_fw_dump(bp);
 		rc = 0;
 	}
+
 	return rc;
 }
 
@@ -5873,7 +6794,7 @@ static int bnx2x_alloc_mem(struct bnx2x *bp)
 	for (i = 0; i < 16*1024; i += 64)
 		* (u64 *)((char *)bp->t2 + i + 56) = bp->t2_mapping + i + 64;
 
-	/* now sixup the last line in the block to point to the next block */
+	/* now fixup the last line in the block to point to the next block */
 	*(u64 *)((char *)bp->t2 + 1024*16-8) = bp->t2_mapping;
 
 	/* Timer block array (MAX_CONN*8) phys uncached for now 1024 conns */
@@ -5954,22 +6875,19 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp)
 	int i;
 
 	free_irq(bp->msix_table[0].vector, bp->dev);
-	DP(NETIF_MSG_IFDOWN, "rleased sp irq (%d)\n",
+	DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
 	   bp->msix_table[0].vector);
 
 	for_each_queue(bp, i) {
-		DP(NETIF_MSG_IFDOWN, "about to rlease fp #%d->%d irq  "
+		DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq  "
 		   "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]);
 	}
 
 }
@@ -5999,7 +6917,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;
 
 	}
@@ -6014,11 +6932,8 @@ static int bnx2x_enable_msix(struct bnx2x *bp)
 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);
 
@@ -6033,7 +6948,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;
 		}
@@ -6113,8 +7029,8 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
 	/* can take a while if any port is running */
 	int timeout = 500;
 
-	/* DP("waiting for state to become %d on IDX [%d]\n",
-	state, sb_idx); */
+	DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
+	   poll ? "polling" : "waiting", state, idx);
 
 	might_sleep();
 
@@ -6132,7 +7048,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--;
@@ -6140,17 +7056,17 @@ 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)
 {
 
-	/* reset IGU staae */
+	/* reset IGU state */
 	bnx2x_ack_sb(bp, DEF_SB_ID, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
 
 	/* SETUP ramrod */
@@ -6166,12 +7082,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);
 
 }
 
@@ -6181,8 +7098,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;
 
@@ -6192,26 +7109,28 @@ 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;
 	}
 
-	DP(NETIF_MSG_IFUP, "set number of queues to %d\n", bp->num_queues);
-
 	/* if we can't use msix we only need one fp,
 	 * so try to enable msix with the requested number of fp's
 	 * and fallback to inta with one fp
 	 */
 	if (req_irq) {
-
 		if (use_inta) {
 			bp->num_queues = 1;
 		} else {
-			if (use_multi > 1 && use_multi <= 16)
+			if ((use_multi > 1) && (use_multi <= 16))
 				/* user requested number */
 				bp->num_queues = use_multi;
 			else if (use_multi == 1)
@@ -6220,15 +7139,17 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 				bp->num_queues = 1;
 
 			if (bnx2x_enable_msix(bp)) {
-				/* faild to enable msix */
+				/* failed to enable msix */
 				bp->num_queues = 1;
 				if (use_multi)
-					BNX2X_ERR("Muti requested but failed"
+					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);
+
 	if (bnx2x_alloc_mem(bp))
 		return -ENOMEM;
 
@@ -6236,43 +7157,37 @@ 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;
 			}
 		}
 	}
 
 	/* 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;
 	}
 
 
 	atomic_set(&bp->intr_sem, 0);
 
-	/* Reenable SP tasklet */
-	/*if (bp->sp_task_en) { 	       */
-	/*        tasklet_enable(&bp->sp_task);*/
-	/*} else {      		       */
-	/*        bp->sp_task_en = 1;          */
-	/*}     			       */
 
 	/* Setup NIC internals and enable interrupts */
 	bnx2x_nic_init(bp);
 
 	/* 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;
 		}
 	}
 
@@ -6284,11 +7199,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 	netif_poll_enable(bp->dev);
 
 	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);
 
@@ -6312,37 +7227,21 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
 
 	return 0;
 
-stop_netif:
+load_stop_netif:
 	netif_poll_disable(bp->dev);
 
-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;
-}
-
-static void bnx2x_netif_stop(struct bnx2x *bp)
-{
-	bp->rx_mode = BNX2X_RX_MODE_NONE;
-	bnx2x_set_storm_rx_mode(bp);
-
-	bnx2x_disable_int_sync(bp);
-	bnx2x_link_reset(bp);
-
-	netif_poll_disable(bp->dev);
-
-	if (netif_running(bp->dev)) {
-		netif_tx_disable(bp->dev);
-		bp->dev->trans_start = jiffies; /* prevent tx timeout */
-	}
+	return -EBUSY;
 }
 
 static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
@@ -6396,20 +7295,20 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index)
 
 	int rc;
 
-	/* halt the connnection */
+	/* halt the connection */
 	bp->fp[index].state = BNX2X_FP_STATE_HALTING;
 	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, 0, 0);
 
 
 	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index,
 				       &(bp->fp[index].state), 1);
-	if (rc) /* timout */
+	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_DELETED, index,
+	return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
 				 &(bp->fp[index].state), 1);
 
 }
@@ -6417,8 +7316,8 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index)
 
 static void bnx2x_stop_leading(struct bnx2x *bp)
 {
-
-	/* if the other port is hadling traffic,
+	u16 dsb_sp_prod_idx;
+	/* if the other port is handling traffic,
 	   this can take a lot of time */
 	int timeout = 500;
 
@@ -6432,52 +7331,70 @@ 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 stil 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);
+	netif_poll_disable(bp->dev);
+	/* 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;
@@ -6494,28 +7411,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)
@@ -6526,8 +7452,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;
@@ -6563,7 +7488,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
 					  SUPPORTED_100baseT_Half |
 					  SUPPORTED_100baseT_Full |
 					  SUPPORTED_1000baseT_Full |
-					  SUPPORTED_2500baseT_Full |
+					  SUPPORTED_2500baseX_Full |
 					  SUPPORTED_TP | SUPPORTED_FIBRE |
 					  SUPPORTED_Autoneg |
 					  SUPPORTED_Pause |
@@ -6576,10 +7501,10 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
 
 			bp->phy_flags |= PHY_SGMII_FLAG;
 
-			bp->supported |= (/* SUPPORTED_10baseT_Half |
-					     SUPPORTED_10baseT_Full |
-					     SUPPORTED_100baseT_Half |
-					     SUPPORTED_100baseT_Full |*/
+			bp->supported |= (SUPPORTED_10baseT_Half |
+					  SUPPORTED_10baseT_Full |
+					  SUPPORTED_100baseT_Half |
+					  SUPPORTED_100baseT_Full |
 					  SUPPORTED_1000baseT_Full |
 					  SUPPORTED_TP | SUPPORTED_FIBRE |
 					  SUPPORTED_Autoneg |
@@ -6615,7 +7540,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
 					  SUPPORTED_100baseT_Half |
 					  SUPPORTED_100baseT_Full |
 					  SUPPORTED_1000baseT_Full |
-					  SUPPORTED_2500baseT_Full |
+					  SUPPORTED_2500baseX_Full |
 					  SUPPORTED_10000baseT_Full |
 					  SUPPORTED_TP | SUPPORTED_FIBRE |
 					  SUPPORTED_Autoneg |
@@ -6624,12 +7549,46 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
 			break;
 
 		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+			BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n",
+					ext_phy_type);
+
+			bp->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 (8705/6)\n",
+			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);
+			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);
+			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);
 			break;
@@ -6686,7 +7645,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
 				   SUPPORTED_1000baseT_Full);
 
 	if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
-		bp->supported &= ~SUPPORTED_2500baseT_Full;
+		bp->supported &= ~SUPPORTED_2500baseX_Full;
 
 	if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
 		bp->supported &= ~SUPPORTED_10000baseT_Full;
@@ -6706,13 +7665,8 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 			bp->req_line_speed = 0;
 			bp->advertising = bp->supported;
 		} else {
-			u32 ext_phy_type;
-
-			ext_phy_type = XGXS_EXT_PHY_TYPE(bp);
-			if ((ext_phy_type ==
-				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
-			    (ext_phy_type ==
-				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) {
+			if (XGXS_EXT_PHY_TYPE(bp) ==
+				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) {
 				/* force 10G, no AN */
 				bp->req_line_speed = SPEED_10000;
 				bp->advertising =
@@ -6729,8 +7683,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 		break;
 
 	case PORT_FEATURE_LINK_SPEED_10M_FULL:
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
+		if (bp->supported & SUPPORTED_10baseT_Full) {
 			bp->req_line_speed = SPEED_10;
 			bp->advertising = (ADVERTISED_10baseT_Full |
 					   ADVERTISED_TP);
@@ -6744,8 +7697,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 		break;
 
 	case PORT_FEATURE_LINK_SPEED_10M_HALF:
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
+		if (bp->supported & SUPPORTED_10baseT_Half) {
 			bp->req_line_speed = SPEED_10;
 			bp->req_duplex = DUPLEX_HALF;
 			bp->advertising = (ADVERTISED_10baseT_Half |
@@ -6760,8 +7712,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 		break;
 
 	case PORT_FEATURE_LINK_SPEED_100M_FULL:
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+		if (bp->supported & SUPPORTED_100baseT_Full) {
 			bp->req_line_speed = SPEED_100;
 			bp->advertising = (ADVERTISED_100baseT_Full |
 					   ADVERTISED_TP);
@@ -6775,8 +7726,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 		break;
 
 	case PORT_FEATURE_LINK_SPEED_100M_HALF:
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+		if (bp->supported & SUPPORTED_100baseT_Half) {
 			bp->req_line_speed = SPEED_100;
 			bp->req_duplex = DUPLEX_HALF;
 			bp->advertising = (ADVERTISED_100baseT_Half |
@@ -6791,8 +7741,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 		break;
 
 	case PORT_FEATURE_LINK_SPEED_1G:
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) {
+		if (bp->supported & SUPPORTED_1000baseT_Full) {
 			bp->req_line_speed = SPEED_1000;
 			bp->advertising = (ADVERTISED_1000baseT_Full |
 					   ADVERTISED_TP);
@@ -6806,10 +7755,9 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 		break;
 
 	case PORT_FEATURE_LINK_SPEED_2_5G:
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) {
+		if (bp->supported & SUPPORTED_2500baseX_Full) {
 			bp->req_line_speed = SPEED_2500;
-			bp->advertising = (ADVERTISED_2500baseT_Full |
+			bp->advertising = (ADVERTISED_2500baseX_Full |
 					   ADVERTISED_TP);
 		} else {
 			BNX2X_ERR("NVRAM config error. "
@@ -6823,15 +7771,7 @@ 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->phy_flags & PHY_XGXS_FLAG)) {
-			BNX2X_ERR("NVRAM config error. "
-				  "Invalid link_config 0x%x"
-				  "  phy_flags 0x%x\n",
-				  bp->link_config, bp->phy_flags);
-			return;
-		}
-		if (bp->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
+		if (bp->supported & SUPPORTED_10000baseT_Full) {
 			bp->req_line_speed = SPEED_10000;
 			bp->advertising = (ADVERTISED_10000baseT_Full |
 					   ADVERTISED_FIBRE);
@@ -6858,43 +7798,13 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp)
 
 	bp->req_flow_ctrl = (bp->link_config &
 			     PORT_FEATURE_FLOW_CONTROL_MASK);
-	/* Please refer to Table 28B-3 of the 802.3ab-1999 spec */
-	switch (bp->req_flow_ctrl) {
-	case FLOW_CTRL_AUTO:
+	if ((bp->req_flow_ctrl == FLOW_CTRL_AUTO) &&
+	    (bp->supported & SUPPORTED_Autoneg))
 		bp->req_autoneg |= AUTONEG_FLOW_CTRL;
-		if (bp->dev->mtu <= 4500) {
-			bp->pause_mode = PAUSE_BOTH;
-			bp->advertising |= (ADVERTISED_Pause |
-					    ADVERTISED_Asym_Pause);
-		} else {
-			bp->pause_mode = PAUSE_ASYMMETRIC;
-			bp->advertising |= ADVERTISED_Asym_Pause;
-		}
-		break;
 
-	case FLOW_CTRL_TX:
-		bp->pause_mode = PAUSE_ASYMMETRIC;
-		bp->advertising |= ADVERTISED_Asym_Pause;
-		break;
-
-	case FLOW_CTRL_RX:
-	case FLOW_CTRL_BOTH:
-		bp->pause_mode = PAUSE_BOTH;
-		bp->advertising |= (ADVERTISED_Pause |
-				    ADVERTISED_Asym_Pause);
-		break;
-
-	case FLOW_CTRL_NONE:
-	default:
-		bp->pause_mode = PAUSE_NONE;
-		bp->advertising &= ~(ADVERTISED_Pause |
-				     ADVERTISED_Asym_Pause);
-		break;
-	}
-	BNX2X_DEV_INFO("req_autoneg 0x%x  req_flow_ctrl 0x%x\n"
-	     KERN_INFO "  pause_mode %d  advertising 0x%x\n",
-		       bp->req_autoneg, bp->req_flow_ctrl,
-		       bp->pause_mode, bp->advertising);
+	BNX2X_DEV_INFO("req_autoneg 0x%x  req_flow_ctrl 0x%x"
+		       "  advertising 0x%x\n",
+		       bp->req_autoneg, bp->req_flow_ctrl, bp->advertising);
 }
 
 static void bnx2x_get_hwinfo(struct bnx2x *bp)
@@ -6928,15 +7838,15 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp)
 	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("MCP validity signature bad\n");
+		BNX2X_ERR("BAD MCP validity signature\n");
 
-	bp->fw_seq = (SHMEM_RD(bp, drv_fw_mb[port].drv_mb_header) &
+	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->serdes_config =
-		SHMEM_RD(bp, dev_info.port_hw_config[bp->port].serdes_config);
+		SHMEM_RD(bp, dev_info.port_hw_config[port].serdes_config);
 	bp->lane_config =
 		SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config);
 	bp->ext_phy_config =
@@ -6949,13 +7859,13 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp)
 	bp->link_config =
 		SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
 
-	BNX2X_DEV_INFO("hw_config (%08x)  serdes_config (%08x)\n"
+	BNX2X_DEV_INFO("hw_config (%08x) board (%08x)  serdes_config (%08x)\n"
 	     KERN_INFO "  lane_config (%08x)  ext_phy_config (%08x)\n"
 	     KERN_INFO "  speed_cap_mask (%08x)  link_config (%08x)"
 		       "  fw_seq (%08x)\n",
-		       bp->hw_config, bp->serdes_config, bp->lane_config,
-		       bp->ext_phy_config, bp->speed_cap_mask,
-		       bp->link_config, bp->fw_seq);
+		       bp->hw_config, bp->board, bp->serdes_config,
+		       bp->lane_config, bp->ext_phy_config,
+		       bp->speed_cap_mask, bp->link_config, bp->fw_seq);
 
 	switch_cfg = (bp->link_config & PORT_FEATURE_CONNECTED_SWITCH_MASK);
 	bnx2x_link_settings_supported(bp, switch_cfg);
@@ -7009,14 +7919,8 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp)
 	return;
 
 set_mac: /* only supposed to happen on emulation/FPGA */
-	BNX2X_ERR("warning constant MAC workaround active\n");
-	bp->dev->dev_addr[0] = 0;
-	bp->dev->dev_addr[1] = 0x50;
-	bp->dev->dev_addr[2] = 0xc2;
-	bp->dev->dev_addr[3] = 0x2c;
-	bp->dev->dev_addr[4] = 0x71;
-	bp->dev->dev_addr[5] = port ? 0x0d : 0x0e;
-
+	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);
 
 }
@@ -7043,19 +7947,34 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	}
 
 	if (bp->phy_flags & PHY_XGXS_FLAG) {
-		cmd->port = PORT_FIBRE;
-	} else {
+		u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp);
+
+		switch (ext_phy_type) {
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+			cmd->port = PORT_FIBRE;
+			break;
+
+		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+			cmd->port = PORT_TP;
+			break;
+
+		default:
+			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
+			   bp->ext_phy_config);
+		}
+	} else
 		cmd->port = PORT_TP;
-	}
 
 	cmd->phy_address = bp->phy_addr;
 	cmd->transceiver = XCVR_INTERNAL;
 
-	if (bp->req_autoneg & AUTONEG_SPEED) {
+	if (bp->req_autoneg & AUTONEG_SPEED)
 		cmd->autoneg = AUTONEG_ENABLE;
-	} else {
+	else
 		cmd->autoneg = AUTONEG_DISABLE;
-	}
 
 	cmd->maxtxpkt = 0;
 	cmd->maxrxpkt = 0;
@@ -7086,8 +8005,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
 	switch (cmd->port) {
 	case PORT_TP:
-		if (!(bp->supported & SUPPORTED_TP))
+		if (!(bp->supported & SUPPORTED_TP)) {
+			DP(NETIF_MSG_LINK, "TP not supported\n");
 			return -EINVAL;
+		}
 
 		if (bp->phy_flags & PHY_XGXS_FLAG) {
 			bnx2x_link_reset(bp);
@@ -7097,8 +8018,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		break;
 
 	case PORT_FIBRE:
-		if (!(bp->supported & SUPPORTED_FIBRE))
+		if (!(bp->supported & SUPPORTED_FIBRE)) {
+			DP(NETIF_MSG_LINK, "FIBRE not supported\n");
 			return -EINVAL;
+		}
 
 		if (!(bp->phy_flags & PHY_XGXS_FLAG)) {
 			bnx2x_link_reset(bp);
@@ -7108,12 +8031,15 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		break;
 
 	default:
+		DP(NETIF_MSG_LINK, "Unknown port type\n");
 		return -EINVAL;
 	}
 
 	if (cmd->autoneg == AUTONEG_ENABLE) {
-		if (!(bp->supported & SUPPORTED_Autoneg))
+		if (!(bp->supported & SUPPORTED_Autoneg)) {
+			DP(NETIF_MSG_LINK, "Aotoneg not supported\n");
 			return -EINVAL;
+		}
 
 		/* advertise the requested speed and duplex if supported */
 		cmd->advertising &= bp->supported;
@@ -7128,14 +8054,22 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		switch (cmd->speed) {
 		case SPEED_10:
 			if (cmd->duplex == DUPLEX_FULL) {
-				if (!(bp->supported & SUPPORTED_10baseT_Full))
+				if (!(bp->supported &
+				      SUPPORTED_10baseT_Full)) {
+					DP(NETIF_MSG_LINK,
+					   "10M full not supported\n");
 					return -EINVAL;
+				}
 
 				advertising = (ADVERTISED_10baseT_Full |
 					       ADVERTISED_TP);
 			} else {
-				if (!(bp->supported & SUPPORTED_10baseT_Half))
+				if (!(bp->supported &
+				      SUPPORTED_10baseT_Half)) {
+					DP(NETIF_MSG_LINK,
+					   "10M half not supported\n");
 					return -EINVAL;
+				}
 
 				advertising = (ADVERTISED_10baseT_Half |
 					       ADVERTISED_TP);
@@ -7145,15 +8079,21 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		case SPEED_100:
 			if (cmd->duplex == DUPLEX_FULL) {
 				if (!(bp->supported &
-						SUPPORTED_100baseT_Full))
+						SUPPORTED_100baseT_Full)) {
+					DP(NETIF_MSG_LINK,
+					   "100M full not supported\n");
 					return -EINVAL;
+				}
 
 				advertising = (ADVERTISED_100baseT_Full |
 					       ADVERTISED_TP);
 			} else {
 				if (!(bp->supported &
-						SUPPORTED_100baseT_Half))
+						SUPPORTED_100baseT_Half)) {
+					DP(NETIF_MSG_LINK,
+					   "100M half not supported\n");
 					return -EINVAL;
+				}
 
 				advertising = (ADVERTISED_100baseT_Half |
 					       ADVERTISED_TP);
@@ -7161,39 +8101,54 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 			break;
 
 		case SPEED_1000:
-			if (cmd->duplex != DUPLEX_FULL)
+			if (cmd->duplex != DUPLEX_FULL) {
+				DP(NETIF_MSG_LINK, "1G half not supported\n");
 				return -EINVAL;
+			}
 
-			if (!(bp->supported & SUPPORTED_1000baseT_Full))
+			if (!(bp->supported & SUPPORTED_1000baseT_Full)) {
+				DP(NETIF_MSG_LINK, "1G full not supported\n");
 				return -EINVAL;
+			}
 
 			advertising = (ADVERTISED_1000baseT_Full |
 				       ADVERTISED_TP);
 			break;
 
 		case SPEED_2500:
-			if (cmd->duplex != DUPLEX_FULL)
+			if (cmd->duplex != DUPLEX_FULL) {
+				DP(NETIF_MSG_LINK,
+				   "2.5G half not supported\n");
 				return -EINVAL;
+			}
 
-			if (!(bp->supported & SUPPORTED_2500baseT_Full))
+			if (!(bp->supported & SUPPORTED_2500baseX_Full)) {
+				DP(NETIF_MSG_LINK,
+				   "2.5G full not supported\n");
 				return -EINVAL;
+			}
 
-			advertising = (ADVERTISED_2500baseT_Full |
+			advertising = (ADVERTISED_2500baseX_Full |
 				       ADVERTISED_TP);
 			break;
 
 		case SPEED_10000:
-			if (cmd->duplex != DUPLEX_FULL)
+			if (cmd->duplex != DUPLEX_FULL) {
+				DP(NETIF_MSG_LINK, "10G half not supported\n");
 				return -EINVAL;
+			}
 
-			if (!(bp->supported & SUPPORTED_10000baseT_Full))
+			if (!(bp->supported & SUPPORTED_10000baseT_Full)) {
+				DP(NETIF_MSG_LINK, "10G full not supported\n");
 				return -EINVAL;
+			}
 
 			advertising = (ADVERTISED_10000baseT_Full |
 				       ADVERTISED_FIBRE);
 			break;
 
 		default:
+			DP(NETIF_MSG_LINK, "Unsupported speed\n");
 			return -EINVAL;
 		}
 
@@ -7393,8 +8348,7 @@ static void bnx2x_disable_nvram_access(struct bnx2x *bp)
 static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, u32 *ret_val,
 				  u32 cmd_flags)
 {
-	int rc;
-	int count, i;
+	int count, i, rc;
 	u32 val;
 
 	/* build the command word */
@@ -7447,13 +8401,13 @@ static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
 
 	if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
 		DP(NETIF_MSG_NVM,
-		   "Invalid paramter: offset 0x%x  buf_size 0x%x\n",
+		   "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 paramter: offset (0x%x) +"
+		DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
 				  " buf_size (0x%x) > flash_size (0x%x)\n",
 		   offset, buf_size, bp->flash_size);
 		return -EINVAL;
@@ -7514,8 +8468,7 @@ static int bnx2x_get_eeprom(struct net_device *dev,
 static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val,
 				   u32 cmd_flags)
 {
-	int rc;
-	int count, i;
+	int count, i, rc;
 
 	/* build the command word */
 	cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR;
@@ -7552,7 +8505,7 @@ static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val,
 	return rc;
 }
 
-#define BYTE_OFFSET(offset)     	(8 * (offset & 0x03))
+#define BYTE_OFFSET(offset)		(8 * (offset & 0x03))
 
 static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
 			      int buf_size)
@@ -7563,7 +8516,7 @@ static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
 	u32 val;
 
 	if (offset + buf_size > bp->flash_size) {
-		DP(NETIF_MSG_NVM, "Invalid paramter: offset (0x%x) +"
+		DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
 				  " buf_size (0x%x) > flash_size (0x%x)\n",
 		   offset, buf_size, bp->flash_size);
 		return -EINVAL;
@@ -7616,13 +8569,13 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
 
 	if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
 		DP(NETIF_MSG_NVM,
-		   "Invalid paramter: offset 0x%x  buf_size 0x%x\n",
+		   "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 paramter: offset (0x%x) +"
+		DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
 				  " buf_size (0x%x) > flash_size (0x%x)\n",
 		   offset, buf_size, bp->flash_size);
 		return -EINVAL;
@@ -7783,52 +8736,29 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
 	   DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
 	   epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
 
-	bp->req_flow_ctrl = FLOW_CTRL_AUTO;
 	if (epause->autoneg) {
-		bp->req_autoneg |= AUTONEG_FLOW_CTRL;
-		if (bp->dev->mtu <= 4500) {
-			bp->pause_mode = PAUSE_BOTH;
-			bp->advertising |= (ADVERTISED_Pause |
-					    ADVERTISED_Asym_Pause);
-		} else {
-			bp->pause_mode = PAUSE_ASYMMETRIC;
-			bp->advertising |= ADVERTISED_Asym_Pause;
+		if (!(bp->supported & SUPPORTED_Autoneg)) {
+			DP(NETIF_MSG_LINK, "Aotoneg not supported\n");
+			return -EINVAL;
 		}
 
-	} else {
+		bp->req_autoneg |= AUTONEG_FLOW_CTRL;
+	} else
 		bp->req_autoneg &= ~AUTONEG_FLOW_CTRL;
 
-		if (epause->rx_pause)
-			bp->req_flow_ctrl |= FLOW_CTRL_RX;
-		if (epause->tx_pause)
-			bp->req_flow_ctrl |= FLOW_CTRL_TX;
-
-		switch (bp->req_flow_ctrl) {
-		case FLOW_CTRL_AUTO:
-			bp->req_flow_ctrl = FLOW_CTRL_NONE;
-			bp->pause_mode = PAUSE_NONE;
-			bp->advertising &= ~(ADVERTISED_Pause |
-					     ADVERTISED_Asym_Pause);
-			break;
+	bp->req_flow_ctrl = FLOW_CTRL_AUTO;
 
-		case FLOW_CTRL_TX:
-			bp->pause_mode = PAUSE_ASYMMETRIC;
-			bp->advertising |= ADVERTISED_Asym_Pause;
-			break;
+	if (epause->rx_pause)
+		bp->req_flow_ctrl |= FLOW_CTRL_RX;
+	if (epause->tx_pause)
+		bp->req_flow_ctrl |= FLOW_CTRL_TX;
 
-		case FLOW_CTRL_RX:
-		case FLOW_CTRL_BOTH:
-			bp->pause_mode = PAUSE_BOTH;
-			bp->advertising |= (ADVERTISED_Pause |
-					    ADVERTISED_Asym_Pause);
-			break;
-		}
-	}
+	if (!(bp->req_autoneg & AUTONEG_FLOW_CTRL) &&
+	    (bp->req_flow_ctrl == FLOW_CTRL_AUTO))
+		bp->req_flow_ctrl = FLOW_CTRL_NONE;
 
-	DP(NETIF_MSG_LINK, "req_autoneg 0x%x  req_flow_ctrl 0x%x\n"
-	   DP_LEVEL "  pause_mode %d  advertising 0x%x\n",
-	   bp->req_autoneg, bp->req_flow_ctrl, bp->pause_mode,
-	   bp->advertising);
+	DP(NETIF_MSG_LINK, "req_autoneg 0x%x  req_flow_ctrl 0x%x\n",
+	   bp->req_autoneg, bp->req_flow_ctrl);
 
 	bnx2x_stop_stats(bp);
 	bnx2x_link_initialize(bp);
@@ -7901,81 +8831,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)
@@ -8133,9 +9069,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);
@@ -8312,7 +9246,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			       ETH_TX_BD_ETH_ADDR_TYPE_SHIFT);
 	tx_bd->general_data |= 1; /* header nbd */
 
-	/* remeber the first bd of the packet */
+	/* remember the first bd of the packet */
 	tx_buf->first_bd = bd_prod;
 
 	DP(NETIF_MSG_TX_QUEUED,
@@ -8332,7 +9266,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);
@@ -8341,7 +9275,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);
 
@@ -8385,7 +9319,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",
@@ -8425,7 +9359,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			tx_bd->vlan = cpu_to_le16(pkt_prod);
 			/* this marks the bd
 			 * as one that has no individual mapping
-			 * the FW ignors this flag in a bd not maked start
+			 * the FW ignores this flag in a bd not marked start
 			 */
 			tx_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_SW_LSO;
 			DP(NETIF_MSG_TX_QUEUED,
@@ -8502,9 +9436,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();
@@ -8541,16 +9477,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;
 }
@@ -8582,7 +9515,7 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	case SIOCGMIIPHY:
 		data->phy_id = bp->phy_addr;
 
-		/* fallthru */
+		/* fallthrough */
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
@@ -8631,7 +9564,7 @@ static int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 		return -EINVAL;
 
 	/* This does not race with packet allocation
-	 * because the actuall alloc size is
+	 * because the actual alloc size is
 	 * only updated as part of load
 	 */
 	dev->mtu = new_mtu;
@@ -8675,7 +9608,7 @@ static void bnx2x_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 		bp->vlgrp->vlan_devices[vid] = NULL;
 
 	if (netif_running(dev))
-		bnx2x_set_rx_mode(dev);
+		bnx2x_set_client_config(bp);
 }
 
 
@@ -8706,14 +9639,18 @@ static void bnx2x_reset_task(void *data)
 	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,
@@ -8794,8 +9731,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, bp);
 	INIT_WORK(&bp->sp_task, bnx2x_sp_task, bp);
 
@@ -8824,7 +9759,7 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev,
 	bnx2x_get_hwinfo(bp);
 
 	if (CHIP_REV(bp) == CHIP_REV_FPGA) {
-		printk(KERN_ERR PFX "FPGA detacted. MCP disabled,"
+		printk(KERN_ERR PFX "FPGA detected. MCP disabled,"
 		       " will only init first device\n");
 		onefunc = 1;
 		nomcp = 1;
@@ -8893,6 +9828,23 @@ err_out:
 	return rc;
 }
 
+static int __devinit bnx2x_get_pcie_width(struct bnx2x *bp)
+{
+	u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
+
+	val = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;
+	return val;
+}
+
+/* return value of 1=2.5GHz 2=5GHz */
+static int __devinit bnx2x_get_pcie_speed(struct bnx2x *bp)
+{
+	u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
+
+	val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
+	return val;
+}
+
 static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
 {
@@ -8917,6 +9869,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
 	if (port && onefunc) {
 		printk(KERN_ERR PFX "second function disabled. exiting\n");
+		free_netdev(dev);
 		return 0;
 	}
 
@@ -8959,7 +9912,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
 	rc = register_netdev(dev);
 	if (rc) {
-		printk(KERN_ERR PFX "Cannot register net device\n");
+		dev_err(&pdev->dev, "Cannot register net device\n");
 		if (bp->regview)
 			iounmap(bp->regview);
 		if (bp->doorbells)
@@ -8974,21 +9927,18 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 	pci_set_drvdata(pdev, dev);
 
 	bp->name = board_info[ent->driver_data].name;
-	printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz "
-	       "found at mem %lx, IRQ %d, ",
-	       dev->name, bp->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),
-	       ((bp->flags & PCIX_FLAG) ? "-X" : ""),
-	       ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
-	       bp->bus_speed_mhz,
-	       dev->base_addr,
-	       bp->pdev->irq);
+	       bnx2x_get_pcie_width(bp),
+	       (bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz",
+	       dev->base_addr, bp->pdev->irq);
 
-	printk("node addr ");
-	for (i = 0; i < 6; i++)
-		printk("%2.2x", dev->dev_addr[i]);
-	printk("\n");
+	printk(KERN_INFO "node addr ");
+        for (i = 0; i < 6; i++)
+                printk(KERN_INFO "%2.2x", dev->dev_addr[i]);
+	printk(KERN_INFO "\n");
 
 	return 0;
 }
@@ -8996,10 +9946,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)
@@ -9017,34 +9973,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);
 
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index a4f4c04..176f4a2 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -1,6 +1,6 @@
 /* bnx2x.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2007 Broadcom Corporation
+ * Copyright (c) 2007-2008 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
 #define BNX2X_MSG_STATS 		0x20000 /* was: NETIF_MSG_TIMER */
 #define NETIF_MSG_NVM   		0x40000 /* was: NETIF_MSG_HW */
 #define NETIF_MSG_DMAE  		0x80000 /* was: NETIF_MSG_HW */
+#define BNX2X_MSG_SP			0x100000 /* was: NETIF_MSG_INTR */
+#define BNX2X_MSG_FP			0x200000 /* was: NETIF_MSG_INTR */
 
 #define DP_LEVEL			KERN_NOTICE     /* was: KERN_DEBUG */
 
@@ -40,6 +42,12 @@
 		__LINE__, bp->dev?(bp->dev->name):"?", ##__args); \
 	} while (0)
 
+/* for logging (never masked) */
+#define BNX2X_LOG(__fmt, __args...) do { \
+	printk(KERN_NOTICE "[%s:%d(%s)]" __fmt, __FUNCTION__, \
+		__LINE__, bp->dev?(bp->dev->name):"?", ##__args); \
+	} while (0)
+
 /* before we have a dev->name use dev_info() */
 #define BNX2X_DEV_INFO(__fmt, __args...) do { \
 	if (bp->msglevel & NETIF_MSG_PROBE) \
@@ -421,8 +429,6 @@ struct bnx2x_fastpath {
 #define BNX2X_FP_STATE_OPEN     	0xa0000
 #define BNX2X_FP_STATE_HALTING  	0xb0000
 #define BNX2X_FP_STATE_HALTED   	0xc0000
-#define BNX2X_FP_STATE_DELETED  	0xd0000
-#define BNX2X_FP_STATE_CLOSE_IRQ	0xe0000
 
 	int     		index;
 
@@ -503,7 +509,6 @@ struct bnx2x {
 	struct eth_spe  	*spq;
 	dma_addr_t      	spq_mapping;
 	u16     		spq_prod_idx;
-	u16     		dsb_sp_prod_idx;
 	struct eth_spe  	*spq_prod_bd;
 	struct eth_spe  	*spq_last_bd;
 	u16     		*dsb_sp_prod;
@@ -515,7 +520,7 @@ struct bnx2x {
 	 */
 	u8      		stat_pending;
 
-	/* End of fileds used in the performance code paths */
+	/* End of fields used in the performance code paths */
 
 	int     		panic;
 	int     		msglevel;
@@ -538,7 +543,6 @@ struct bnx2x {
 	spinlock_t      	phy_lock;
 
 	struct work_struct      reset_task;
-	u16     		in_reset_task;
 	u16			sp_running;
 	struct work_struct      sp_task;
 
@@ -553,7 +557,6 @@ struct bnx2x {
 #define CHIP_ID(bp)     		(((bp)->chip_id) & 0xfffffff0)
 
 #define CHIP_NUM(bp)    		(((bp)->chip_id) & 0xffff0000)
-#define CHIP_NUM_5710   		0x57100000
 
 #define CHIP_REV(bp)    		(((bp)->chip_id) & 0x0000f000)
 #define CHIP_REV_Ax     		0x00000000
@@ -572,7 +575,8 @@ struct bnx2x {
 	u32     		fw_mb;
 
 	u32     		hw_config;
-	u32     		serdes_config;
+	u32			board;
+	u32			serdes_config;
 	u32     		lane_config;
 	u32     		ext_phy_config;
 #define XGXS_EXT_PHY_TYPE(bp)   	(bp->ext_phy_config & \
@@ -593,11 +597,11 @@ struct bnx2x {
 	u8      		tx_lane_swap;
 
 	u8      		link_up;
+	u8			phy_link_up;
 
 	u32     		supported;
 /* link settings - missing defines */
 #define SUPPORTED_2500baseT_Full	(1 << 15)
-#define SUPPORTED_CX4   		(1 << 16)
 
 	u32     		phy_flags;
 /*#define PHY_SERDES_FLAG       		0x1*/
@@ -642,16 +646,9 @@ struct bnx2x {
 #define FLOW_CTRL_BOTH  		PORT_FEATURE_FLOW_CONTROL_BOTH
 #define FLOW_CTRL_NONE  		PORT_FEATURE_FLOW_CONTROL_NONE
 
-	u32     		pause_mode;
-#define PAUSE_NONE      		0
-#define PAUSE_SYMMETRIC 		1
-#define PAUSE_ASYMMETRIC		2
-#define PAUSE_BOTH      		3
-
 	u32     		advertising;
 /* link settings - missing defines */
 #define ADVERTISED_2500baseT_Full       (1 << 15)
-#define ADVERTISED_CX4  		(1 << 16)
 
 	u32     		link_status;
 	u32     		line_speed;
@@ -665,6 +662,8 @@ struct bnx2x {
 #define NVRAM_TIMEOUT_COUNT     	30000
 #define NVRAM_PAGE_SIZE 		256
 
+	u8			wol;
+
 	int     		rx_ring_size;
 
 	u16     		tx_quick_cons_trip_int;
@@ -716,9 +715,6 @@ struct bnx2x {
 #endif
 
 	char    		*name;
-	u16     		bus_speed_mhz;
-	u8      		wol;
-	u8      		pad;
 
 	/* used to synchronize stats collecting */
 	int     		stats_state;
@@ -856,8 +852,8 @@ struct bnx2x {
 #define MAX_SPQ_PENDING 		8
 
 
-#define BNX2X_NUM_STATS 		31
-#define BNX2X_NUM_TESTS 		2
+#define BNX2X_NUM_STATS			34
+#define BNX2X_NUM_TESTS			1
 
 
 #define DPM_TRIGER_TYPE 		0x40
@@ -867,6 +863,15 @@ struct bnx2x {
 		       DPM_TRIGER_TYPE); \
 	} while (0)
 
+/* PCIE link and speed */
+#define PCICFG_LINK_WIDTH		0x1f00000
+#define PCICFG_LINK_WIDTH_SHIFT		20
+#define PCICFG_LINK_SPEED		0xf0000
+#define PCICFG_LINK_SPEED_SHIFT		16
+
+#define BMAC_CONTROL_RX_ENABLE		2
+
+#define pbd_tcp_flags(skb)  	(ntohl(tcp_flag_word(tcp_hdr(skb)))>>16 & 0xff)
 
 /* stuff added to make the code fit 80Col */
 
@@ -939,13 +944,13 @@ struct bnx2x {
 #define LINK_16GTFD     		LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
 #define LINK_16GXFD     		LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
 
-#define NIG_STATUS_INTERRUPT_XGXS0_LINK10G \
+#define NIG_STATUS_XGXS0_LINK10G \
 		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
-#define NIG_XGXS0_LINK_STATUS \
+#define NIG_STATUS_XGXS0_LINK_STATUS \
 		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
-#define NIG_XGXS0_LINK_STATUS_SIZE \
+#define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
 		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
-#define NIG_SERDES0_LINK_STATUS \
+#define NIG_STATUS_SERDES0_LINK_STATUS \
 		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
 #define NIG_MASK_MI_INT \
 		NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
diff --git a/drivers/net/bnx2x_fw_defs.h b/drivers/net/bnx2x_fw_defs.h
index 62a6eb8..3b96890 100644
--- a/drivers/net/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x_fw_defs.h
@@ -1,6 +1,6 @@
 /* bnx2x_fw_defs.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2007 Broadcom Corporation
+ * Copyright (c) 2007-2008 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h
index 6fd959c..b21075c 100644
--- a/drivers/net/bnx2x_hsi.h
+++ b/drivers/net/bnx2x_hsi.h
@@ -1,6 +1,6 @@
 /* bnx2x_hsi.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2007 Broadcom Corporation
+ * Copyright (c) 2007-2008 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -8,169 +8,9 @@
  */
 
 
-#define FUNC_0				0
-#define FUNC_1				1
-#define FUNC_MAX			2
-
-
-/* This value (in milliseconds) determines the frequency of the driver
- * issuing the PULSE message code.  The firmware monitors this periodic
- * pulse to determine when to switch to an OS-absent mode. */
-#define DRV_PULSE_PERIOD_MS		250
-
-/* This value (in milliseconds) determines how long the driver should
- * wait for an acknowledgement from the firmware before timing out.  Once
- * the firmware has timed out, the driver will assume there is no firmware
- * running and there won't be any firmware-driver synchronization during a
- * driver reset. */
-#define FW_ACK_TIME_OUT_MS		5000
-
-#define FW_ACK_POLL_TIME_MS		1
-
-#define FW_ACK_NUM_OF_POLL	(FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
-
-/* LED Blink rate that will achieve ~15.9Hz */
-#define LED_BLINK_RATE_VAL		480
-
-/****************************************************************************
- * Driver <-> FW Mailbox						    *
- ****************************************************************************/
-struct drv_fw_mb {
-	u32 drv_mb_header;
-#define DRV_MSG_CODE_MASK			0xffff0000
-#define DRV_MSG_CODE_LOAD_REQ			0x10000000
-#define DRV_MSG_CODE_LOAD_DONE			0x11000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN		0x20000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 	0x20010000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 	0x20020000
-#define DRV_MSG_CODE_UNLOAD_DONE		0x21000000
-#define DRV_MSG_CODE_DIAG_ENTER_REQ		0x50000000
-#define DRV_MSG_CODE_DIAG_EXIT_REQ		0x60000000
-#define DRV_MSG_CODE_VALIDATE_KEY		0x70000000
-#define DRV_MSG_CODE_GET_CURR_KEY		0x80000000
-#define DRV_MSG_CODE_GET_UPGRADE_KEY		0x81000000
-#define DRV_MSG_CODE_GET_MANUF_KEY		0x82000000
-#define DRV_MSG_CODE_LOAD_L2B_PRAM		0x90000000
-
-#define DRV_MSG_SEQ_NUMBER_MASK 		0x0000ffff
-
-	u32 drv_mb_param;
-
-	u32 fw_mb_header;
-#define FW_MSG_CODE_MASK			0xffff0000
-#define FW_MSG_CODE_DRV_LOAD_COMMON		0x11000000
-#define FW_MSG_CODE_DRV_LOAD_PORT		0x12000000
-#define FW_MSG_CODE_DRV_LOAD_REFUSED		0x13000000
-#define FW_MSG_CODE_DRV_LOAD_DONE		0x14000000
-#define FW_MSG_CODE_DRV_UNLOAD_COMMON		0x21000000
-#define FW_MSG_CODE_DRV_UNLOAD_PORT		0x22000000
-#define FW_MSG_CODE_DRV_UNLOAD_DONE		0x23000000
-#define FW_MSG_CODE_DIAG_ENTER_DONE		0x50000000
-#define FW_MSG_CODE_DIAG_REFUSE 		0x51000000
-#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS	0x70000000
-#define FW_MSG_CODE_VALIDATE_KEY_FAILURE	0x71000000
-#define FW_MSG_CODE_GET_KEY_DONE		0x80000000
-#define FW_MSG_CODE_NO_KEY			0x8f000000
-#define FW_MSG_CODE_LIC_INFO_NOT_READY		0x8f800000
-#define FW_MSG_CODE_L2B_PRAM_LOADED		0x90000000
-#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE	0x91000000
-#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE	0x92000000
-#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE	0x93000000
-#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE	0x94000000
-
-#define FW_MSG_SEQ_NUMBER_MASK			0x0000ffff
-
-	u32 fw_mb_param;
-
-	u32 link_status;
-	/* Driver should update this field on any link change event */
-
-#define LINK_STATUS_LINK_FLAG_MASK		0x00000001
-#define LINK_STATUS_LINK_UP			0x00000001
-#define LINK_STATUS_SPEED_AND_DUPLEX_MASK	0x0000001E
-#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE	(0<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10THD		(1<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD		(2<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD		(3<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100T4		(4<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD		(5<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD		(6<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD		(7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD		(7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD		(8<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD		(9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD		(9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD		(10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD		(10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD		(11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD		(11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD		(12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD		(12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD		(13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD		(13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD		(14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD		(14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD		(15<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD		(15<<1)
-
-#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK		0x00000020
-#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED		0x00000020
-
-#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE		0x00000040
-#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK	0x00000080
-#define LINK_STATUS_PARALLEL_DETECTION_USED		0x00000080
-
-#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE	0x00000200
-#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE	0x00000400
-#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE		0x00000800
-#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE	0x00001000
-#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE	0x00002000
-#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE		0x00004000
-#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE		0x00008000
-
-#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK		0x00010000
-#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED		0x00010000
-
-#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK		0x00020000
-#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED		0x00020000
-
-#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK	0x000C0000
-#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE	(0<<18)
-#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE	(1<<18)
-#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE	(2<<18)
-#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE		(3<<18)
-
-#define LINK_STATUS_SERDES_LINK 			0x00100000
-
-#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE	0x00200000
-#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE	0x00400000
-#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 	0x00800000
-#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 	0x01000000
-#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE	0x02000000
-#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 	0x04000000
-#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 	0x08000000
-#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 	0x10000000
-
-	u32 drv_pulse_mb;
-#define DRV_PULSE_SEQ_MASK				0x00007fff
-#define DRV_PULSE_SYSTEM_TIME_MASK			0xffff0000
-	/* The system time is in the format of
-	 * (year-2001)*12*32 + month*32 + day. */
-#define DRV_PULSE_ALWAYS_ALIVE				0x00008000
-	/* Indicate to the firmware not to go into the
-	 * OS-absent when it is not getting driver pulse.
-	 * This is used for debugging as well for PXE(MBA). */
-
-	u32 mcp_pulse_mb;
-#define MCP_PULSE_SEQ_MASK				0x00007fff
-#define MCP_PULSE_ALWAYS_ALIVE				0x00008000
-	/* Indicates to the driver not to assert due to lack
-	 * of MCP response */
-#define MCP_EVENT_MASK					0xffff0000
-#define MCP_EVENT_OTHER_DRIVER_RESET_REQ		0x00010000
-
-};
-
+#define PORT_0				0
+#define PORT_1				1
+#define PORT_MAX			2
 
 /****************************************************************************
  * Shared HW configuration						    *
@@ -249,7 +89,7 @@ struct shared_hw_cfg {					 /* NVRAM Offset */
 #define SHARED_HW_CFG_SMBUS_TIMING_100KHZ	    0x00000000
 #define SHARED_HW_CFG_SMBUS_TIMING_400KHZ	    0x00001000
 
-#define SHARED_HW_CFG_HIDE_FUNC1		    0x00002000
+#define SHARED_HW_CFG_HIDE_PORT1		    0x00002000
 
 	u32 power_dissipated;					/* 0x11c */
 #define SHARED_HW_CFG_POWER_DIS_CMN_MASK	    0xff000000
@@ -290,6 +130,8 @@ struct shared_hw_cfg {					 /* NVRAM Offset */
 #define SHARED_HW_CFG_BOARD_TYPE_BCM957710T1015G    0x00000006
 #define SHARED_HW_CFG_BOARD_TYPE_BCM957710A1020G    0x00000007
 #define SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G    0x00000008
+#define SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G    0x00000009
+#define SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G    0x0000000a
 
 #define SHARED_HW_CFG_BOARD_VER_MASK		    0xffff0000
 #define SHARED_HW_CFG_BOARD_VER_SHIFT		    16
@@ -304,13 +146,12 @@ struct shared_hw_cfg {					 /* NVRAM Offset */
 
 };
 
+
 /****************************************************************************
  * Port HW configuration						    *
  ****************************************************************************/
-struct port_hw_cfg {	/* function 0: 0x12c-0x2bb, function 1: 0x2bc-0x44b */
+struct port_hw_cfg {			    /* port 0: 0x12c  port 1: 0x2bc */
 
-	/* Fields below are port specific (in anticipation of dual port
-	   devices */
 	u32 pci_id;
 #define PORT_HW_CFG_PCI_VENDOR_ID_MASK		    0xffff0000
 #define PORT_HW_CFG_PCI_DEVICE_ID_MASK		    0x0000ffff
@@ -420,6 +261,8 @@ struct port_hw_cfg {	/* function 0: 0x12c-0x2bb, function 1: 0x2bc-0x44b */
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706	    0x00000500
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8276	    0x00000600
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481	    0x00000700
+#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101	    0x00000800
+#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE	    0x0000fd00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN	    0x0000ff00
 
 #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK	    0x000000ff
@@ -462,11 +305,13 @@ struct port_hw_cfg {	/* function 0: 0x12c-0x2bb, function 1: 0x2bc-0x44b */
 
 };
 
+
 /****************************************************************************
  * Shared Feature configuration 					    *
  ****************************************************************************/
 struct shared_feat_cfg {				 /* NVRAM Offset */
-	u32 bmc_common; 					/* 0x450 */
+
+	u32 config;						/* 0x450 */
 #define SHARED_FEATURE_BMC_ECHO_MODE_EN 	    0x00000001
 
 };
@@ -475,7 +320,8 @@ struct shared_feat_cfg {				 /* NVRAM Offset */
 /****************************************************************************
  * Port Feature configuration						    *
  ****************************************************************************/
-struct port_feat_cfg {	/* function 0: 0x454-0x4c7, function 1: 0x4c8-0x53b */
+struct port_feat_cfg {			    /* port 0: 0x454  port 1: 0x4c8 */
+
 	u32 config;
 #define PORT_FEATURE_BAR1_SIZE_MASK		    0x0000000f
 #define PORT_FEATURE_BAR1_SIZE_SHIFT		    0
@@ -609,8 +455,7 @@ struct port_feat_cfg {	/* function 0: 0x454-0x4c7, function 1: 0x4c8-0x53b */
 #define PORT_FEATURE_SMBUS_ADDR_MASK		    0x000000fe
 #define PORT_FEATURE_SMBUS_ADDR_SHIFT		    1
 
-	u32 iscsib_boot_cfg;
-#define PORT_FEATURE_ISCSIB_SKIP_TARGET_BOOT	    0x00000001
+	u32 reserved1;
 
 	u32 link_config;    /* Used as HW defaults for the driver */
 #define PORT_FEATURE_CONNECTED_SWITCH_MASK	    0x03000000
@@ -657,20 +502,201 @@ struct port_feat_cfg {	/* function 0: 0x454-0x4c7, function 1: 0x4c8-0x53b */
 };
 
 
+/*****************************************************************************
+ * Device Information							     *
+ *****************************************************************************/
+struct dev_info {						     /* size */
+
+	u32    bc_rev; /* 8 bits each: major, minor, build */	        /* 4 */
+
+	struct shared_hw_cfg	 shared_hw_config;		       /* 40 */
+
+	struct port_hw_cfg	 port_hw_config[PORT_MAX];      /* 400*2=800 */
+
+	struct shared_feat_cfg	 shared_feature_config; 	        /* 4 */
+
+	struct port_feat_cfg	 port_feature_config[PORT_MAX]; /* 116*2=232 */
+
+};
+
+
+#define FUNC_0				0
+#define FUNC_1				1
+#define E1_FUNC_MAX			2
+#define FUNC_MAX			E1_FUNC_MAX
+
+
+/* This value (in milliseconds) determines the frequency of the driver
+ * issuing the PULSE message code.  The firmware monitors this periodic
+ * pulse to determine when to switch to an OS-absent mode. */
+#define DRV_PULSE_PERIOD_MS		250
+
+/* This value (in milliseconds) determines how long the driver should
+ * wait for an acknowledgement from the firmware before timing out.  Once
+ * the firmware has timed out, the driver will assume there is no firmware
+ * running and there won't be any firmware-driver synchronization during a
+ * driver reset. */
+#define FW_ACK_TIME_OUT_MS		5000
+
+#define FW_ACK_POLL_TIME_MS		1
+
+#define FW_ACK_NUM_OF_POLL	(FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
+
+/* LED Blink rate that will achieve ~15.9Hz */
+#define LED_BLINK_RATE_VAL		480
+
 /****************************************************************************
- * Device Information							    *
+ * Driver <-> FW Mailbox						    *
  ****************************************************************************/
-struct dev_info {						    /* size */
+struct drv_port_mb {
+
+	u32 link_status;
+	/* Driver should update this field on any link change event */
+
+#define LINK_STATUS_LINK_FLAG_MASK			0x00000001
+#define LINK_STATUS_LINK_UP				0x00000001
+#define LINK_STATUS_SPEED_AND_DUPLEX_MASK		0x0000001E
+#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE	(0<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_10THD		(1<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD		(2<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD		(3<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_100T4		(4<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD		(5<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD		(6<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD		(7<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD		(7<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD		(8<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD		(9<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD		(9<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD		(10<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD		(10<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD		(11<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD		(11<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD		(12<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD		(12<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD		(13<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD		(13<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD		(14<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD		(14<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD		(15<<1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD		(15<<1)
+
+#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK		0x00000020
+#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED		0x00000020
+
+#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE		0x00000040
+#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK	0x00000080
+#define LINK_STATUS_PARALLEL_DETECTION_USED		0x00000080
+
+#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE	0x00000200
+#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE	0x00000400
+#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE		0x00000800
+#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE	0x00001000
+#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE	0x00002000
+#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE		0x00004000
+#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE		0x00008000
+
+#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK		0x00010000
+#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED		0x00010000
+
+#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK		0x00020000
+#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED		0x00020000
+
+#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK	0x000C0000
+#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE	(0<<18)
+#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE	(1<<18)
+#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE	(2<<18)
+#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE		(3<<18)
+
+#define LINK_STATUS_SERDES_LINK 			0x00100000
+
+#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE	0x00200000
+#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE	0x00400000
+#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 	0x00800000
+#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 	0x01000000
+#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE	0x02000000
+#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 	0x04000000
+#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 	0x08000000
+#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 	0x10000000
 
-	u32    bc_rev; /* 8 bits each: major, minor, build */	       /* 4 */
+	u32 reserved[3];
 
-	struct shared_hw_cfg	 shared_hw_config;		      /* 40 */
+};
+
+
+struct drv_func_mb {
+
+	u32 drv_mb_header;
+#define DRV_MSG_CODE_MASK				0xffff0000
+#define DRV_MSG_CODE_LOAD_REQ				0x10000000
+#define DRV_MSG_CODE_LOAD_DONE				0x11000000
+#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN			0x20000000
+#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 		0x20010000
+#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 		0x20020000
+#define DRV_MSG_CODE_UNLOAD_DONE			0x21000000
+#define DRV_MSG_CODE_DIAG_ENTER_REQ			0x50000000
+#define DRV_MSG_CODE_DIAG_EXIT_REQ			0x60000000
+#define DRV_MSG_CODE_VALIDATE_KEY			0x70000000
+#define DRV_MSG_CODE_GET_CURR_KEY			0x80000000
+#define DRV_MSG_CODE_GET_UPGRADE_KEY			0x81000000
+#define DRV_MSG_CODE_GET_MANUF_KEY			0x82000000
+#define DRV_MSG_CODE_LOAD_L2B_PRAM			0x90000000
+
+#define DRV_MSG_SEQ_NUMBER_MASK 			0x0000ffff
+
+	u32 drv_mb_param;
+
+	u32 fw_mb_header;
+#define FW_MSG_CODE_MASK				0xffff0000
+#define FW_MSG_CODE_DRV_LOAD_COMMON			0x10100000
+#define FW_MSG_CODE_DRV_LOAD_PORT			0x10110000
+#define FW_MSG_CODE_DRV_LOAD_FUNCTION			0x10120000
+#define FW_MSG_CODE_DRV_LOAD_REFUSED			0x10200000
+#define FW_MSG_CODE_DRV_LOAD_DONE			0x11100000
+#define FW_MSG_CODE_DRV_UNLOAD_COMMON			0x20100000
+#define FW_MSG_CODE_DRV_UNLOAD_PORT			0x20110000
+#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 		0x20120000
+#define FW_MSG_CODE_DRV_UNLOAD_DONE			0x21100000
+#define FW_MSG_CODE_DIAG_ENTER_DONE			0x50100000
+#define FW_MSG_CODE_DIAG_REFUSE 			0x50200000
+#define FW_MSG_CODE_DIAG_EXIT_DONE			0x60100000
+#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS		0x70100000
+#define FW_MSG_CODE_VALIDATE_KEY_FAILURE		0x70200000
+#define FW_MSG_CODE_GET_KEY_DONE			0x80100000
+#define FW_MSG_CODE_NO_KEY				0x80f00000
+#define FW_MSG_CODE_LIC_INFO_NOT_READY			0x80f80000
+#define FW_MSG_CODE_L2B_PRAM_LOADED			0x90100000
+#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE		0x90210000
+#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE		0x90220000
+#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE		0x90230000
+#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE		0x90240000
+
+#define FW_MSG_SEQ_NUMBER_MASK				0x0000ffff
+
+	u32 fw_mb_param;
+
+	u32 drv_pulse_mb;
+#define DRV_PULSE_SEQ_MASK				0x00007fff
+#define DRV_PULSE_SYSTEM_TIME_MASK			0xffff0000
+	/* The system time is in the format of
+	 * (year-2001)*12*32 + month*32 + day. */
+#define DRV_PULSE_ALWAYS_ALIVE				0x00008000
+	/* Indicate to the firmware not to go into the
+	 * OS-absent when it is not getting driver pulse.
+	 * This is used for debugging as well for PXE(MBA). */
 
-	struct port_hw_cfg	 port_hw_config[FUNC_MAX];     /* 400*2=800 */
+	u32 mcp_pulse_mb;
+#define MCP_PULSE_SEQ_MASK				0x00007fff
+#define MCP_PULSE_ALWAYS_ALIVE				0x00008000
+	/* Indicates to the driver not to assert due to lack
+	 * of MCP response */
+#define MCP_EVENT_MASK					0xffff0000
+#define MCP_EVENT_OTHER_DRIVER_RESET_REQ		0x00010000
 
-	struct shared_feat_cfg	 shared_feature_config; 	       /* 4 */
+	u32 iscsi_boot_signature;
+	u32 iscsi_boot_block_offset;
 
-	struct port_feat_cfg	 port_feature_config[FUNC_MAX];/* 116*2=232 */
+	u32 reserved[3];
 
 };
 
@@ -678,9 +704,8 @@ struct dev_info {						    /* size */
 /****************************************************************************
  * Management firmware state						    *
  ****************************************************************************/
-/* Allocate 320 bytes for management firmware: still not known exactly
- * how much IMD needs. */
-#define MGMTFW_STATE_WORD_SIZE				    80
+/* Allocate 440 bytes for management firmware */
+#define MGMTFW_STATE_WORD_SIZE				    110
 
 struct mgmtfw_state {
 	u32 opaque[MGMTFW_STATE_WORD_SIZE];
@@ -691,31 +716,40 @@ struct mgmtfw_state {
  * Shared Memory Region 						    *
  ****************************************************************************/
 struct shmem_region {			       /*   SharedMem Offset (size) */
-	u32		    validity_map[FUNC_MAX];    /* 0x0 (4 * 2 = 0x8) */
-#define SHR_MEM_VALIDITY_PCI_CFG		    0x00000001
-#define SHR_MEM_VALIDITY_MB			    0x00000002
-#define SHR_MEM_VALIDITY_DEV_INFO		    0x00000004
+
+	u32			validity_map[PORT_MAX];  /* 0x0 (4*2 = 0x8) */
+#define SHR_MEM_FORMAT_REV_ID			    ('A'<<24)
+#define SHR_MEM_FORMAT_REV_MASK 		    0xff000000
+	/* validity bits */
+#define SHR_MEM_VALIDITY_PCI_CFG		    0x00100000
+#define SHR_MEM_VALIDITY_MB			    0x00200000
+#define SHR_MEM_VALIDITY_DEV_INFO		    0x00400000
+#define SHR_MEM_VALIDITY_RESERVED		    0x00000007
 	/* One licensing bit should be set */
 #define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK     0x00000038
 #define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT    0x00000008
 #define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT  0x00000010
 #define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT	    0x00000020
+	/* Active MFW */
+#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN	    0x00000000
+#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI	    0x00000040
+#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 	    0x00000080
+#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI	    0x000000c0
+#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE	    0x000001c0
+#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK	    0x000001c0
 
-	struct drv_fw_mb    drv_fw_mb[FUNC_MAX];     /* 0x8 (28 * 2 = 0x38) */
-
-	struct dev_info     dev_info;			    /* 0x40 (0x438) */
+	struct dev_info 	dev_info;		 /* 0x8     (0x438) */
 
-#ifdef _LICENSE_H
-	license_key_t	    drv_lic_key[FUNC_MAX]; /* 0x478 (52 * 2 = 0x68) */
-#else /* Linux! */
-	u8		    reserved[52*FUNC_MAX];
-#endif
+	u8			reserved[52*PORT_MAX];
 
 	/* FW information (for internal FW use) */
-	u32		    fw_info_fio_offset; 	   /* 0x4e0 (0x4)   */
-	struct mgmtfw_state mgmtfw_state;		   /* 0x4e4 (0x140) */
+	u32			fw_info_fio_offset;    /* 0x4a8       (0x4) */
+	struct mgmtfw_state	mgmtfw_state;	       /* 0x4ac     (0x1b8) */
+
+	struct drv_port_mb	port_mb[PORT_MAX];     /* 0x664 (16*2=0x20) */
+	struct drv_func_mb	func_mb[FUNC_MAX];     /* 0x684 (44*2=0x58) */
 
-};							   /* 0x624 */
+};						       /* 0x6dc */
 
 
 #define BCM_5710_FW_MAJOR_VERSION			4
diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h
index 04f93bf..dcaecc5 100644
--- a/drivers/net/bnx2x_init.h
+++ b/drivers/net/bnx2x_init.h
@@ -1,6 +1,6 @@
 /* bnx2x_init.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2007 Broadcom Corporation
+ * Copyright (c) 2007-2008 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -409,7 +409,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
 
 	pci_read_config_word(bp->pdev,
 			     bp->pcie_cap + PCI_EXP_DEVCTL, (u16 *)&val);
-	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", val);
+	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", (u16)val);
 	w_order = ((val & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
 	r_order = ((val & PCI_EXP_DEVCTL_READRQ) >> 12);
 
@@ -472,10 +472,14 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
 	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
 
 	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
-	REG_WR(bp, PXP2_REG_RQ_WR_MBS0 + 8, w_order);
+	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);
 	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
-	REG_WR(bp, PXP2_REG_RQ_RD_MBS0 + 8, r_order);
+	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
 
+	if (r_order == MAX_RD_ORD)
+		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
+
+	REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
 	REG_WR(bp, PXP2_REG_WR_DMAE_TH, (128 << w_order)/16);
 }
 
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h
index 8605529..5a1aa0b 100644
--- a/drivers/net/bnx2x_reg.h
+++ b/drivers/net/bnx2x_reg.h
@@ -1,6 +1,6 @@
 /* bnx2x_reg.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2007 Broadcom Corporation
+ * Copyright (c) 2007-2008 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
 #define BRB1_REG_BRB1_INT_STS					 0x6011c
 /* [RW 4] Parity mask register #0 read/write */
 #define BRB1_REG_BRB1_PRTY_MASK 				 0x60138
+/* [R 4] Parity register #0 read */
+#define BRB1_REG_BRB1_PRTY_STS					 0x6012c
 /* [RW 10] At address BRB1_IND_FREE_LIST_PRS_CRDT initialize free head. At
    address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
    BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. */
@@ -281,6 +283,8 @@
 #define CDU_REG_CDU_INT_STS					 0x101030
 /* [RW 5] Parity mask register #0 read/write */
 #define CDU_REG_CDU_PRTY_MASK					 0x10104c
+/* [R 5] Parity register #0 read */
+#define CDU_REG_CDU_PRTY_STS					 0x101040
 /* [RC 32] logging of error data in case of a CDU load error:
    {expected_cid[15:0]; xpected_type[2:0]; xpected_region[2:0]; ctive_error;
    ype_error; ctual_active; ctual_compressed_context}; */
@@ -308,6 +312,8 @@
 #define CFC_REG_CFC_INT_STS_CLR 				 0x104100
 /* [RW 4] Parity mask register #0 read/write */
 #define CFC_REG_CFC_PRTY_MASK					 0x104118
+/* [R 4] Parity register #0 read */
+#define CFC_REG_CFC_PRTY_STS					 0x10410c
 /* [RW 21] CID cam access (21:1 - Data; alid - 0) */
 #define CFC_REG_CID_CAM 					 0x104800
 #define CFC_REG_CONTROL0					 0x104028
@@ -354,6 +360,8 @@
 #define CSDM_REG_CSDM_INT_MASK_1				 0xc22ac
 /* [RW 11] Parity mask register #0 read/write */
 #define CSDM_REG_CSDM_PRTY_MASK 				 0xc22bc
+/* [R 11] Parity register #0 read */
+#define CSDM_REG_CSDM_PRTY_STS					 0xc22b0
 #define CSDM_REG_ENABLE_IN1					 0xc2238
 #define CSDM_REG_ENABLE_IN2					 0xc223c
 #define CSDM_REG_ENABLE_OUT1					 0xc2240
@@ -438,6 +446,9 @@
 /* [RW 32] Parity mask register #0 read/write */
 #define CSEM_REG_CSEM_PRTY_MASK_0				 0x200130
 #define CSEM_REG_CSEM_PRTY_MASK_1				 0x200140
+/* [R 32] Parity register #0 read */
+#define CSEM_REG_CSEM_PRTY_STS_0				 0x200124
+#define CSEM_REG_CSEM_PRTY_STS_1				 0x200134
 #define CSEM_REG_ENABLE_IN					 0x2000a4
 #define CSEM_REG_ENABLE_OUT					 0x2000a8
 /* [RW 32] This address space contains all registers and memories that are
@@ -526,6 +537,8 @@
 #define CSEM_REG_TS_9_AS					 0x20005c
 /* [RW 1] Parity mask register #0 read/write */
 #define DBG_REG_DBG_PRTY_MASK					 0xc0a8
+/* [R 1] Parity register #0 read */
+#define DBG_REG_DBG_PRTY_STS					 0xc09c
 /* [RW 2] debug only: These bits indicate the credit for PCI request type 4
    interface; MUST be configured AFTER pci_ext_buffer_strt_addr_lsb/msb are
    configured */
@@ -543,6 +556,8 @@
 #define DMAE_REG_DMAE_INT_MASK					 0x102054
 /* [RW 4] Parity mask register #0 read/write */
 #define DMAE_REG_DMAE_PRTY_MASK 				 0x102064
+/* [R 4] Parity register #0 read */
+#define DMAE_REG_DMAE_PRTY_STS					 0x102058
 /* [RW 1] Command 0 go. */
 #define DMAE_REG_GO_C0						 0x102080
 /* [RW 1] Command 1 go. */
@@ -623,6 +638,8 @@
 #define DORQ_REG_DORQ_INT_STS_CLR				 0x170178
 /* [RW 2] Parity mask register #0 read/write */
 #define DORQ_REG_DORQ_PRTY_MASK 				 0x170190
+/* [R 2] Parity register #0 read */
+#define DORQ_REG_DORQ_PRTY_STS					 0x170184
 /* [RW 8] The address to write the DPM CID to STORM. */
 #define DORQ_REG_DPM_CID_ADDR					 0x170044
 /* [RW 5] The DPM mode CID extraction offset. */
@@ -692,6 +709,8 @@
 #define HC_REG_CONFIG_1 					 0x108004
 /* [RW 3] Parity mask register #0 read/write */
 #define HC_REG_HC_PRTY_MASK					 0x1080a0
+/* [R 3] Parity register #0 read */
+#define HC_REG_HC_PRTY_STS					 0x108094
 /* [RW 17] status block interrupt mask; one in each bit means unmask; zerow
    in each bit means mask; bit 0 - default SB; bit 1 - SB_0; bit 2 - SB_1...
    bit 16- SB_15; addr 0 - port 0; addr 1 - port 1 */
@@ -1127,6 +1146,7 @@
 #define MISC_REG_AEU_GENERAL_ATTN_17				 0xa044
 #define MISC_REG_AEU_GENERAL_ATTN_18				 0xa048
 #define MISC_REG_AEU_GENERAL_ATTN_19				 0xa04c
+#define MISC_REG_AEU_GENERAL_ATTN_10				 0xa028
 #define MISC_REG_AEU_GENERAL_ATTN_11				 0xa02c
 #define MISC_REG_AEU_GENERAL_ATTN_2				 0xa008
 #define MISC_REG_AEU_GENERAL_ATTN_20				 0xa050
@@ -1135,6 +1155,9 @@
 #define MISC_REG_AEU_GENERAL_ATTN_4				 0xa010
 #define MISC_REG_AEU_GENERAL_ATTN_5				 0xa014
 #define MISC_REG_AEU_GENERAL_ATTN_6				 0xa018
+#define MISC_REG_AEU_GENERAL_ATTN_7				 0xa01c
+#define MISC_REG_AEU_GENERAL_ATTN_8				 0xa020
+#define MISC_REG_AEU_GENERAL_ATTN_9				 0xa024
 /* [RW 32] first 32b for inverting the input for function 0; for each bit:
    0= do not invert; 1= invert; mapped as follows: [0] NIG attention for
    function0; [1] NIG attention for function1; [2] GPIO1 mcp; [3] GPIO2 mcp;
@@ -1183,6 +1206,40 @@
    starts at 0x0 for the A0 tape-out and increments by one for each
    all-layer tape-out. */
 #define MISC_REG_CHIP_REV					 0xa40c
+/* [RW 32] The following driver registers(1..6) represent 6 drivers and 32
+   clients. Each client can be controlled by one driver only. One in each
+   bit represent that this driver control the appropriate client (Ex: bit 5
+   is set means this driver control client number 5). addr1 = set; addr0 =
+   clear; read from both addresses will give the same result = status. write
+   to address 1 will set a request to control all the clients that their
+   appropriate bit (in the write command) is set. if the client is free (the
+   appropriate bit in all the other drivers is clear) one will be written to
+   that driver register; if the client isn't free the bit will remain zero.
+   if the appropriate bit is set (the driver request to gain control on a
+   client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
+   interrupt will be asserted). write to address 0 will set a request to
+   free all the clients that their appropriate bit (in the write command) is
+   set. if the appropriate bit is clear (the driver request to free a client
+   it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
+   be asserted). */
+#define MISC_REG_DRIVER_CONTROL_1				 0xa510
+/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
+   these bits is written as a '1'; the corresponding SPIO bit will turn off
+   it's drivers and become an input. This is the reset state of all GPIO
+   pins. The read value of these bits will be a '1' if that last command
+   (#SET; #CLR; or #FLOAT) for this bit was a #FLOAT. (reset value 0xff).
+   [23-20] CLR port 1; 19-16] CLR port 0; When any of these bits is written
+   as a '1'; the corresponding GPIO bit will drive low. The read value of
+   these bits will be a '1' if that last command (#SET; #CLR; or #FLOAT) for
+   this bit was a #CLR. (reset value 0). [15-12] SET port 1; 11-8] port 0;
+   SET When any of these bits is written as a '1'; the corresponding GPIO
+   bit will drive high (if it has that capability). The read value of these
+   bits will be a '1' if that last command (#SET; #CLR; or #FLOAT) for this
+   bit was a #SET. (reset value 0). [7-4] VALUE port 1; [3-0] VALUE port 0;
+   RO; These bits indicate the read value of each of the eight GPIO pins.
+   This is the result value of the pin; not the drive value. Writing these
+   bits will have not effect. */
+#define MISC_REG_GPIO						 0xa490
 /* [RW 1] Setting this bit enables a timer in the GRC block to timeout any
    access that does not finish within
    ~misc_registers_grc_timout_val.grc_timeout_val cycles. When this bit is
@@ -1223,6 +1280,8 @@
 #define MISC_REG_MISC_INT_MASK					 0xa388
 /* [RW 1] Parity mask register #0 read/write */
 #define MISC_REG_MISC_PRTY_MASK 				 0xa398
+/* [R 1] Parity register #0 read */
+#define MISC_REG_MISC_PRTY_STS					 0xa38c
 /* [RW 32] 32 LSB of storm PLL first register; reset val = 0x 071d2911.
    inside order of the bits is: [0] P1 divider[0] (reset value 1); [1] P1
    divider[1] (reset value 0); [2] P1 divider[2] (reset value 0); [3] P1
@@ -1264,6 +1323,55 @@
 /* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is
    shared with the driver resides */
 #define MISC_REG_SHARED_MEM_ADDR				 0xa2b4
+/* [RW 32] SPIO. [31-24] FLOAT When any of these bits is written as a '1';
+   the corresponding SPIO bit will turn off it's drivers and become an
+   input. This is the reset state of all SPIO pins. The read value of these
+   bits will be a '1' if that last command (#SET; #CL; or #FLOAT) for this
+   bit was a #FLOAT. (reset value 0xff). [23-16] CLR When any of these bits
+   is written as a '1'; the corresponding SPIO bit will drive low. The read
+   value of these bits will be a '1' if that last command (#SET; #CLR; or
+#FLOAT) for this bit was a #CLR. (reset value 0). [15-8] SET When any of
+   these bits is written as a '1'; the corresponding SPIO bit will drive
+   high (if it has that capability). The read value of these bits will be a
+   '1' if that last command (#SET; #CLR; or #FLOAT) for this bit was a #SET.
+   (reset value 0). [7-0] VALUE RO; These bits indicate the read value of
+   each of the eight SPIO pins. This is the result value of the pin; not the
+   drive value. Writing these bits will have not effect. Each 8 bits field
+   is divided as follows: [0] VAUX Enable; when pulsed low; enables supply
+   from VAUX. (This is an output pin only; the FLOAT field is not applicable
+   for this pin); [1] VAUX Disable; when pulsed low; disables supply form
+   VAUX. (This is an output pin only; FLOAT field is not applicable for this
+   pin); [2] SEL_VAUX_B - Control to power switching logic. Drive low to
+   select VAUX supply. (This is an output pin only; it is not controlled by
+   the SET and CLR fields; it is controlled by the Main Power SM; the FLOAT
+   field is not applicable for this pin; only the VALUE fields is relevant -
+   it reflects the output value); [3] reserved; [4] spio_4; [5] spio_5; [6]
+   Bit 0 of UMP device ID select; read by UMP firmware; [7] Bit 1 of UMP
+   device ID select; read by UMP firmware. */
+#define MISC_REG_SPIO						 0xa4fc
+/* [RW 8] These bits enable the SPIO_INTs to signals event to the IGU/MC.
+   according to the following map: [3:0] reserved; [4] spio_4 [5] spio_5;
+   [7:0] reserved */
+#define MISC_REG_SPIO_EVENT_EN					 0xa2b8
+/* [RW 32] SPIO INT. [31-24] OLD_CLR Writing a '1' to these bit clears the
+   corresponding bit in the #OLD_VALUE register. This will acknowledge an
+   interrupt on the falling edge of corresponding SPIO input (reset value
+   0). [23-16] OLD_SET Writing a '1' to these bit sets the corresponding bit
+   in the #OLD_VALUE register. This will acknowledge an interrupt on the
+   rising edge of corresponding SPIO input (reset value 0). [15-8] OLD_VALUE
+   RO; These bits indicate the old value of the SPIO input value. When the
+   ~INT_STATE bit is set; this bit indicates the OLD value of the pin such
+   that if ~INT_STATE is set and this bit is '0'; then the interrupt is due
+   to a low to high edge. If ~INT_STATE is set and this bit is '1'; then the
+   interrupt is due to a high to low edge (reset value 0). [7-0] INT_STATE
+   RO; These bits indicate the current SPIO interrupt state for each SPIO
+   pin. This bit is cleared when the appropriate #OLD_SET or #OLD_CLR
+   command bit is written. This bit is set when the SPIO input does not
+   match the current value in #OLD_VALUE (reset value 0). */
+#define MISC_REG_SPIO_INT					 0xa500
+/* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
+   loaded; 0-prepare; -unprepare */
+#define MISC_REG_UNPREPARED					 0xa424
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT	 (0x1<<0)
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS	 (0x1<<9)
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G 	 (0x1<<15)
@@ -1392,6 +1500,9 @@
 #define NIG_REG_NIG_INGRESS_EMAC0_NO_CRC			 0x10044
 /* [RW 1] Input enable for RX PBF LP IF */
 #define NIG_REG_PBF_LB_IN_EN					 0x100b4
+/* [RW 1] Value of this register will be transmitted to port swap when
+   ~nig_registers_strap_override.strap_override =1 */
+#define NIG_REG_PORT_SWAP					 0x10394
 /* [RW 1] output enable for RX parser descriptor IF */
 #define NIG_REG_PRS_EOP_OUT_EN					 0x10104
 /* [RW 1] Input enable for RX parser request IF */
@@ -1410,6 +1521,10 @@
 #define NIG_REG_STAT2_BRB_OCTET 				 0x107e0
 #define NIG_REG_STATUS_INTERRUPT_PORT0				 0x10328
 #define NIG_REG_STATUS_INTERRUPT_PORT1				 0x1032c
+/* [RW 1] port swap mux selection. If this register equal to 0 then port
+   swap is equal to SPIO pin that inputs from ifmux_serdes_swap. If 1 then
+   ort swap is equal to ~nig_registers_port_swap.port_swap */
+#define NIG_REG_STRAP_OVERRIDE					 0x10398
 /* [RW 1] output enable for RX_XCM0 IF */
 #define NIG_REG_XCM0_OUT_EN					 0x100f0
 /* [RW 1] output enable for RX_XCM1 IF */
@@ -1499,6 +1614,8 @@
 #define PB_REG_PB_INT_STS					 0x1c
 /* [RW 4] Parity mask register #0 read/write */
 #define PB_REG_PB_PRTY_MASK					 0x38
+/* [R 4] Parity register #0 read */
+#define PB_REG_PB_PRTY_STS					 0x2c
 #define PRS_REG_A_PRSU_20					 0x40134
 /* [R 8] debug only: CFC load request current credit. Transaction based. */
 #define PRS_REG_CFC_LD_CURRENT_CREDIT				 0x40164
@@ -1590,6 +1707,8 @@
 #define PRS_REG_PRS_INT_STS					 0x40188
 /* [RW 8] Parity mask register #0 read/write */
 #define PRS_REG_PRS_PRTY_MASK					 0x401a4
+/* [R 8] Parity register #0 read */
+#define PRS_REG_PRS_PRTY_STS					 0x40198
 /* [RW 8] Context region for pure acknowledge packets. Used in CFC load
    request message */
 #define PRS_REG_PURE_REGIONS					 0x40024
@@ -1718,6 +1837,9 @@
 /* [RW 32] Parity mask register #0 read/write */
 #define PXP2_REG_PXP2_PRTY_MASK_0				 0x120588
 #define PXP2_REG_PXP2_PRTY_MASK_1				 0x120598
+/* [R 32] Parity register #0 read */
+#define PXP2_REG_PXP2_PRTY_STS_0				 0x12057c
+#define PXP2_REG_PXP2_PRTY_STS_1				 0x12058c
 /* [R 1] Debug only: The 'almost full' indication from each fifo (gives
    indication about backpressure) */
 #define PXP2_REG_RD_ALMOST_FULL_0				 0x120424
@@ -1911,6 +2033,8 @@
 #define PXP2_REG_RQ_HC_ENDIAN_M 				 0x1201a8
 /* [WB 53] Onchip address table */
 #define PXP2_REG_RQ_ONCHIP_AT					 0x122000
+/* [RW 13] Pending read limiter threshold; in Dwords */
+#define PXP2_REG_RQ_PDR_LIMIT					 0x12033c
 /* [RW 2] Endian mode for qm */
 #define PXP2_REG_RQ_QM_ENDIAN_M 				 0x120194
 /* [RW 3] page size in L2P table for QM module; -4k; -8k; -16k; -32k; -64k;
@@ -1921,6 +2045,9 @@
 /* [RW 3] Max burst size filed for read requests port 0; 000 - 128B;
    001:256B; 010: 512B; 11:1K:100:2K; 01:4K */
 #define PXP2_REG_RQ_RD_MBS0					 0x120160
+/* [RW 3] Max burst size filed for read requests port 1; 000 - 128B;
+   001:256B; 010: 512B; 11:1K:100:2K; 01:4K */
+#define PXP2_REG_RQ_RD_MBS1					 0x120168
 /* [RW 2] Endian mode for src */
 #define PXP2_REG_RQ_SRC_ENDIAN_M				 0x12019c
 /* [RW 3] page size in L2P table for SRC module; -4k; -8k; -16k; -32k; -64k;
@@ -2000,10 +2127,17 @@
 /* [RW 3] Max burst size filed for write requests port 0; 000 - 128B;
    001:256B; 010: 512B; */
 #define PXP2_REG_RQ_WR_MBS0					 0x12015c
+/* [RW 3] Max burst size filed for write requests port 1; 000 - 128B;
+   001:256B; 010: 512B; */
+#define PXP2_REG_RQ_WR_MBS1					 0x120164
 /* [RW 10] if Number of entries in dmae fifo will be higer than this
    threshold then has_payload indication will be asserted; the default value
    should be equal to &gt;  write MBS size! */
 #define PXP2_REG_WR_DMAE_TH					 0x120368
+/* [RW 10] if Number of entries in usdmdp fifo will be higer than this
+   threshold then has_payload indication will be asserted; the default value
+   should be equal to &gt;  write MBS size! */
+#define PXP2_REG_WR_USDMDP_TH					 0x120348
 /* [R 1] debug only: Indication if PSWHST arbiter is idle */
 #define PXP_REG_HST_ARB_IS_IDLE 				 0x103004
 /* [R 8] debug only: A bit mask for all PSWHST arbiter clients. '1' means
@@ -2021,6 +2155,8 @@
 #define PXP_REG_PXP_INT_STS_CLR_0				 0x10306c
 /* [RW 26] Parity mask register #0 read/write */
 #define PXP_REG_PXP_PRTY_MASK					 0x103094
+/* [R 26] Parity register #0 read */
+#define PXP_REG_PXP_PRTY_STS					 0x103088
 /* [RW 4] The activity counter initial increment value sent in the load
    request */
 #define QM_REG_ACTCTRINITVAL_0					 0x168040
@@ -2127,6 +2263,8 @@
 #define QM_REG_QM_INT_STS					 0x168438
 /* [RW 9] Parity mask register #0 read/write */
 #define QM_REG_QM_PRTY_MASK					 0x168454
+/* [R 9] Parity register #0 read */
+#define QM_REG_QM_PRTY_STS					 0x168448
 /* [R 32] Current queues in pipeline: Queues from 32 to 63 */
 #define QM_REG_QSTATUS_HIGH					 0x16802c
 /* [R 32] Current queues in pipeline: Queues from 0 to 31 */
@@ -2410,6 +2548,8 @@
 #define SRC_REG_SRC_INT_STS					 0x404ac
 /* [RW 3] Parity mask register #0 read/write */
 #define SRC_REG_SRC_PRTY_MASK					 0x404c8
+/* [R 3] Parity register #0 read */
+#define SRC_REG_SRC_PRTY_STS					 0x404bc
 /* [R 4] Used to read the value of the XX protection CAM occupancy counter. */
 #define TCM_REG_CAM_OCCUP					 0x5017c
 /* [RW 1] CDU AG read Interface enable. If 0 - the request input is
@@ -2730,6 +2870,8 @@
 #define TSDM_REG_TSDM_INT_MASK_1				 0x422ac
 /* [RW 11] Parity mask register #0 read/write */
 #define TSDM_REG_TSDM_PRTY_MASK 				 0x422bc
+/* [R 11] Parity register #0 read */
+#define TSDM_REG_TSDM_PRTY_STS					 0x422b0
 /* [RW 5] The number of time_slots in the arbitration cycle */
 #define TSEM_REG_ARB_CYCLE_SIZE 				 0x180034
 /* [RW 3] The source that is associated with arbitration element 0. Source
@@ -2854,6 +2996,9 @@
 /* [RW 32] Parity mask register #0 read/write */
 #define TSEM_REG_TSEM_PRTY_MASK_0				 0x180120
 #define TSEM_REG_TSEM_PRTY_MASK_1				 0x180130
+/* [R 32] Parity register #0 read */
+#define TSEM_REG_TSEM_PRTY_STS_0				 0x180114
+#define TSEM_REG_TSEM_PRTY_STS_1				 0x180124
 /* [R 5] Used to read the XX protection CAM occupancy counter. */
 #define UCM_REG_CAM_OCCUP					 0xe0170
 /* [RW 1] CDU AG read Interface enable. If 0 - the request input is
@@ -3155,6 +3300,8 @@
 #define USDM_REG_USDM_INT_MASK_1				 0xc42b0
 /* [RW 11] Parity mask register #0 read/write */
 #define USDM_REG_USDM_PRTY_MASK 				 0xc42c0
+/* [R 11] Parity register #0 read */
+#define USDM_REG_USDM_PRTY_STS					 0xc42b4
 /* [RW 5] The number of time_slots in the arbitration cycle */
 #define USEM_REG_ARB_CYCLE_SIZE 				 0x300034
 /* [RW 3] The source that is associated with arbitration element 0. Source
@@ -3279,6 +3426,9 @@
 /* [RW 32] Parity mask register #0 read/write */
 #define USEM_REG_USEM_PRTY_MASK_0				 0x300130
 #define USEM_REG_USEM_PRTY_MASK_1				 0x300140
+/* [R 32] Parity register #0 read */
+#define USEM_REG_USEM_PRTY_STS_0				 0x300124
+#define USEM_REG_USEM_PRTY_STS_1				 0x300134
 /* [RW 2] The queue index for registration on Aux1 counter flag. */
 #define XCM_REG_AUX1_Q						 0x20134
 /* [RW 2] Per each decision rule the queue index to register to. */
@@ -3684,6 +3834,8 @@
 #define XSDM_REG_XSDM_INT_MASK_1				 0x1662ac
 /* [RW 11] Parity mask register #0 read/write */
 #define XSDM_REG_XSDM_PRTY_MASK 				 0x1662bc
+/* [R 11] Parity register #0 read */
+#define XSDM_REG_XSDM_PRTY_STS					 0x1662b0
 /* [RW 5] The number of time_slots in the arbitration cycle */
 #define XSEM_REG_ARB_CYCLE_SIZE 				 0x280034
 /* [RW 3] The source that is associated with arbitration element 0. Source
@@ -3808,6 +3960,9 @@
 /* [RW 32] Parity mask register #0 read/write */
 #define XSEM_REG_XSEM_PRTY_MASK_0				 0x280130
 #define XSEM_REG_XSEM_PRTY_MASK_1				 0x280140
+/* [R 32] Parity register #0 read */
+#define XSEM_REG_XSEM_PRTY_STS_0				 0x280124
+#define XSEM_REG_XSEM_PRTY_STS_1				 0x280134
 #define MCPR_NVM_ACCESS_ENABLE_EN				 (1L<<0)
 #define MCPR_NVM_ACCESS_ENABLE_WR_EN				 (1L<<1)
 #define MCPR_NVM_ADDR_NVM_ADDR_VALUE				 (0xffffffL<<0)
@@ -3847,6 +4002,8 @@
 #define EMAC_MDIO_COMM_START_BUSY				 (1L<<29)
 #define EMAC_MDIO_MODE_AUTO_POLL				 (1L<<4)
 #define EMAC_MDIO_MODE_CLAUSE_45				 (1L<<31)
+#define EMAC_MDIO_MODE_CLOCK_CNT				 (0x3fL<<16)
+#define EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT			 16
 #define EMAC_MODE_25G_MODE					 (1L<<5)
 #define EMAC_MODE_ACPI_RCVD					 (1L<<20)
 #define EMAC_MODE_HALF_DUPLEX					 (1L<<1)
@@ -3874,6 +4031,17 @@
 #define EMAC_RX_MTU_SIZE_JUMBO_ENA				 (1L<<31)
 #define EMAC_TX_MODE_EXT_PAUSE_EN				 (1L<<3)
 #define EMAC_TX_MODE_RESET					 (1L<<0)
+#define MISC_REGISTERS_GPIO_1					 1
+#define MISC_REGISTERS_GPIO_2					 2
+#define MISC_REGISTERS_GPIO_3					 3
+#define MISC_REGISTERS_GPIO_CLR_POS				 16
+#define MISC_REGISTERS_GPIO_FLOAT				 (0xffL<<24)
+#define MISC_REGISTERS_GPIO_FLOAT_POS				 24
+#define MISC_REGISTERS_GPIO_INPUT_HI_Z				 2
+#define MISC_REGISTERS_GPIO_OUTPUT_HIGH 			 1
+#define MISC_REGISTERS_GPIO_OUTPUT_LOW				 0
+#define MISC_REGISTERS_GPIO_PORT_SHIFT				 4
+#define MISC_REGISTERS_GPIO_SET_POS				 8
 #define MISC_REGISTERS_RESET_REG_1_CLEAR			 0x588
 #define MISC_REGISTERS_RESET_REG_1_SET				 0x584
 #define MISC_REGISTERS_RESET_REG_2_CLEAR			 0x598
@@ -3891,6 +4059,25 @@
 #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW	 (0x1<<4)
 #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB (0x1<<8)
 #define MISC_REGISTERS_RESET_REG_3_SET				 0x5a4
+#define MISC_REGISTERS_SPIO_4					 4
+#define MISC_REGISTERS_SPIO_5					 5
+#define MISC_REGISTERS_SPIO_7					 7
+#define MISC_REGISTERS_SPIO_CLR_POS				 16
+#define MISC_REGISTERS_SPIO_FLOAT				 (0xffL<<24)
+#define GRC_MISC_REGISTERS_SPIO_FLOAT7				 0x80000000
+#define GRC_MISC_REGISTERS_SPIO_FLOAT6				 0x40000000
+#define GRC_MISC_REGISTERS_SPIO_FLOAT5				 0x20000000
+#define GRC_MISC_REGISTERS_SPIO_FLOAT4				 0x10000000
+#define MISC_REGISTERS_SPIO_FLOAT_POS				 24
+#define MISC_REGISTERS_SPIO_INPUT_HI_Z				 2
+#define MISC_REGISTERS_SPIO_INT_OLD_SET_POS			 16
+#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 			 1
+#define MISC_REGISTERS_SPIO_OUTPUT_LOW				 0
+#define MISC_REGISTERS_SPIO_SET_POS				 8
+#define HW_LOCK_MAX_RESOURCE_VALUE				 31
+#define HW_LOCK_RESOURCE_8072_MDIO				 0
+#define HW_LOCK_RESOURCE_GPIO					 1
+#define HW_LOCK_RESOURCE_SPIO					 2
 #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR		      (1<<18)
 #define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT		      (1<<31)
 #define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT		      (1<<9)
@@ -3918,6 +4105,7 @@
 #define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT		      (1<<3)
 #define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR		      (1<<2)
 #define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR	      (1<<22)
+#define AEU_INPUTS_ATTN_BITS_SPIO5			      (1<<15)
 #define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT		      (1<<27)
 #define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT	      (1<<5)
 #define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT		      (1<<25)
@@ -4206,6 +4394,9 @@
 #define MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE	0x4000
 #define MDIO_XGXS_BLOCK2_TX_LN_SWAP			0x11
 #define MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE		0x8000
+#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G		0x14
+#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS	0x0001
+#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS	0x0010
 #define MDIO_XGXS_BLOCK2_TEST_MODE_LANE 		0x15
 
 #define MDIO_REG_BANK_GP_STATUS 			0x8120
@@ -4362,11 +4553,13 @@
 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_SGMII_MODE   0x0001
 
 
+#define EXT_PHY_AUTO_NEG_DEVAD				0x7
 #define EXT_PHY_OPT_PMA_PMD_DEVAD			0x1
 #define EXT_PHY_OPT_WIS_DEVAD				0x2
 #define EXT_PHY_OPT_PCS_DEVAD				0x3
 #define EXT_PHY_OPT_PHY_XS_DEVAD			0x4
 #define EXT_PHY_OPT_CNTL				0x0
+#define EXT_PHY_OPT_CNTL2				0x7
 #define EXT_PHY_OPT_PMD_RX_SD				0xa
 #define EXT_PHY_OPT_PMD_MISC_CNTL			0xca0a
 #define EXT_PHY_OPT_PHY_IDENTIFIER			0xc800
@@ -4378,11 +4571,24 @@
 #define EXT_PHY_OPT_LASI_STATUS 			0x9005
 #define EXT_PHY_OPT_PCS_STATUS				0x0020
 #define EXT_PHY_OPT_XGXS_LANE_STATUS			0x0018
+#define EXT_PHY_OPT_AN_LINK_STATUS			0x8304
+#define EXT_PHY_OPT_AN_CL37_CL73			0x8370
+#define EXT_PHY_OPT_AN_CL37_FD				0xffe4
+#define EXT_PHY_OPT_AN_CL37_AN				0xffe0
+#define EXT_PHY_OPT_AN_ADV				0x11
 
 #define EXT_PHY_KR_PMA_PMD_DEVAD			0x1
 #define EXT_PHY_KR_PCS_DEVAD				0x3
 #define EXT_PHY_KR_AUTO_NEG_DEVAD			0x7
 #define EXT_PHY_KR_CTRL 				0x0000
+#define EXT_PHY_KR_STATUS				0x0001
+#define EXT_PHY_KR_AUTO_NEG_COMPLETE		    	0x0020
+#define EXT_PHY_KR_AUTO_NEG_ADVERT			0x0010
+#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE	    	0x0400
+#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_ASYMMETRIC 	0x0800
+#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_BOTH	    	0x0C00
+#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK	    	0x0C00
+#define EXT_PHY_KR_LP_AUTO_NEG				0x0013
 #define EXT_PHY_KR_CTRL2				0x0007
 #define EXT_PHY_KR_PCS_STATUS				0x0020
 #define EXT_PHY_KR_PMD_CTRL				0x0096
@@ -4391,4 +4597,8 @@
 #define EXT_PHY_KR_MISC_CTRL1				0xca85
 #define EXT_PHY_KR_GEN_CTRL				0xca10
 #define EXT_PHY_KR_ROM_CODE				0xca19
+#define EXT_PHY_KR_ROM_RESET_INTERNAL_MP		0x0188
+#define EXT_PHY_KR_ROM_MICRO_RESET			0x018a
+
+#define EXT_PHY_SFX7101_XGXS_TEST1	    0xc00a