[BNX2X]: Correct Link management
authorEliezer Tamir <eliezert@broadcom.com>
Thu, 28 Feb 2008 19:51:50 +0000 (11:51 -0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 28 Feb 2008 19:51:50 +0000 (11:51 -0800)
Properly protect PHY access between two devices on the same board with
a HW lock.

Use GPIO to clear all previous configurations before changing link
parameters.

Shut down the external PHY in case of fan failure.

Reducing the MDC/MDIO clock to 2.5MHz due to problems with some
devices.

Resolve the flow control response according to autoneg with external
PHY.

Unmasking all PHY interrupts in single write to prevent a race in the
interrupts order.

LASI indication fixes to work with peculiarities of PHYs.

Disable MAC RX to avoid a HW bug when closing the MAC under traffic.

Disable parallel detection on HiGig due to HW limitation.

Updating the shared memory structure to work with the current
bootcode.

Signed-off-by: Eliezer Tamir <eliezert@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bnx2x.c
drivers/net/bnx2x.h
drivers/net/bnx2x_fw_defs.h
drivers/net/bnx2x_hsi.h
drivers/net/bnx2x_reg.h

index 7786716..5cd7850 100644 (file)
@@ -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
@@ -65,7 +65,7 @@
 
 #define DRV_MODULE_VERSION      "0.40.15"
 #define DRV_MODULE_RELDATE      "$DateTime: 2007/11/15 07:28:37 $"
-#define BNX2X_BC_VER           0x040009
+#define BNX2X_BC_VER           0x040200
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT             (5*HZ)
@@ -78,7 +78,7 @@ 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 $");
+MODULE_INFO(cvs_version, "$Revision: #404 $");
 
 static int use_inta;
 static int poll;
@@ -1181,12 +1181,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 +1401,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 +1451,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 +1512,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 +1600,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)
@@ -1476,10 +1646,73 @@ static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val)
  * 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;
@@ -1501,45 +1734,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 +1795,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 +1906,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)
@@ -1684,38 +1929,38 @@ static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g)
        /* first reset all status
         * 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 +1971,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
+                        */
+                       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
                         */
-                       val = (rx_sd & pcs_status);
+                       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)
@@ -1935,6 +2271,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;
@@ -2233,7 +2598,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);
 }
 
@@ -2295,19 +2660,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);
@@ -2318,14 +2683,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),
@@ -2337,7 +2703,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);
@@ -2352,7 +2718,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);
@@ -2428,7 +2795,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)
@@ -2476,12 +2845,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 |=
@@ -2491,8 +2860,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);
        }
 }
 
@@ -2626,7 +3001,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;
@@ -2639,23 +3014,94 @@ static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x *bp)
 {
        u32 an_adv;
 
-       /* for AN, we are always publishing full duplex */
-       an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
+       /* for AN, we are always publishing full duplex */
+       an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
+
+       /* 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;
 
-       /* 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;
+               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);
@@ -2753,47 +3199,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");
@@ -2801,49 +3362,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 external 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 external 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);
 */
@@ -2855,10 +3602,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 external phy int\n");
                        break;
 
                default:
@@ -2872,8 +3615,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);
@@ -2884,15 +3641,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:
@@ -2931,6 +3697,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);
@@ -3011,11 +3778,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)
@@ -3074,6 +3841,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,
@@ -3082,21 +3854,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
@@ -3177,6 +3973,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) |
@@ -4335,7 +5132,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];
@@ -4345,7 +5142,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;
@@ -4354,9 +5151,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)
@@ -4370,11 +5167,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);
 }
 
@@ -5266,8 +6063,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);
@@ -5487,6 +6286,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 */
@@ -5646,6 +6467,18 @@ 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 PCIE errors for debug */
@@ -5670,9 +6503,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,12 +6518,12 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode)
 /* 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 */
@@ -5698,19 +6531,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;
 }
 
@@ -6559,7 +7393,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 |
@@ -6572,10 +7406,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 |
@@ -6611,7 +7445,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 |
@@ -6620,12 +7454,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;
@@ -6682,7 +7550,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;
@@ -6702,13 +7570,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 =
@@ -6725,8 +7588,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);
@@ -6740,8 +7602,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 |
@@ -6756,8 +7617,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);
@@ -6771,8 +7631,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 |
@@ -6787,8 +7646,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);
@@ -6802,10 +7660,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. "
@@ -6819,15 +7676,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);
@@ -6854,43 +7703,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)
@@ -6923,16 +7742,16 @@ 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");
+               != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+               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 =
@@ -6945,13 +7764,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);
@@ -7005,14 +7824,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);
 
 }
@@ -7039,19 +7852,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;
@@ -7082,8 +7910,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);
@@ -7093,8 +7923,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);
@@ -7104,12 +7936,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;
@@ -7124,14 +7959,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);
@@ -7141,15 +7984,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);
@@ -7157,39 +8006,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;
                }
 
@@ -7389,8 +8253,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 */
@@ -7510,8 +8373,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;
@@ -7548,7 +8410,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)
@@ -7779,52 +8641,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);
index ea91008..dc423e5 100644 (file)
@@ -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 */
 
                __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) \
@@ -574,7 +582,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 & \
@@ -595,11 +604,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*/
@@ -644,16 +653,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;
@@ -667,6 +669,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;
@@ -718,9 +722,6 @@ struct bnx2x {
 #endif
 
        char                    *name;
-       u16                     bus_speed_mhz;
-       u8                      wol;
-       u8                      pad;
 
        /* used to synchronize stats collecting */
        int                     stats_state;
@@ -873,6 +874,7 @@ struct bnx2x {
 #define PCICFG_LINK_SPEED              0xf0000
 #define PCICFG_LINK_SPEED_SHIFT                16
 
+#define BMAC_CONTROL_RX_ENABLE         2
 /* stuff added to make the code fit 80Col */
 
 #define TPA_TYPE_START                 ETH_FAST_PATH_RX_CQE_START_FLG
@@ -944,13 +946,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
Simple merge
Simple merge
Simple merge