]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorDavid S. Miller <davem@davemloft.net>
Tue, 29 Nov 2011 00:21:10 +0000 (19:21 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Nov 2011 00:21:10 +0000 (19:21 -0500)
12 files changed:
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/tg3.c
include/net/flow_keys.h [new file with mode: 0644]
net/core/Makefile
net/core/dev.c
net/core/flow_dissector.c [new file with mode: 0644]
net/ipv4/tcp.c
net/sched/cls_flow.c
net/sched/sch_sfb.c

index ec318711f483b24b339f1fa7ea87bd098a9a1895..c679ed9d3035bc6a39a365fb757f537b811e97ce 100644 (file)
@@ -352,7 +352,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                DP(NETIF_MSG_LINK, "Unsupported port type\n");
                return -EINVAL;
        }
-       /* Save new config in case command complete successuly */
+       /* Save new config in case command complete successully */
        new_multi_phy_config = bp->link_params.multi_phy_config;
        /* Get the new cfg_idx */
        cfg_idx = bnx2x_get_link_cfg_idx(bp);
@@ -1749,8 +1749,18 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
                        return -EINVAL;
                break;
        case BNX2X_MAC_LOOPBACK:
-               bp->link_params.loopback_mode = CHIP_IS_E3(bp) ?
-                                               LOOPBACK_XMAC : LOOPBACK_BMAC;
+               if (CHIP_IS_E3(bp)) {
+                       int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+                       if (bp->port.supported[cfg_idx] &
+                           (SUPPORTED_10000baseT_Full |
+                            SUPPORTED_20000baseMLD2_Full |
+                            SUPPORTED_20000baseKR2_Full))
+                               bp->link_params.loopback_mode = LOOPBACK_XMAC;
+                       else
+                               bp->link_params.loopback_mode = LOOPBACK_UMAC;
+               } else
+                       bp->link_params.loopback_mode = LOOPBACK_BMAC;
+
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                break;
        default:
index 882f48f0a03cdb47568bff2e67b95cc1cdab5cb3..4df9505b67b62e1d482460cc83fcfb6999a83746 100644 (file)
@@ -27,7 +27,6 @@
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
 
-
 /********************************************************/
 #define ETH_HLEN                       14
 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
 #define EDC_MODE_LIMITING                              0x0044
 #define EDC_MODE_PASSIVE_DAC                   0x0055
 
+/* BRB default for class 0 E2 */
+#define DEFAULT0_E2_BRB_MAC_PAUSE_XOFF_THR     170
+#define DEFAULT0_E2_BRB_MAC_PAUSE_XON_THR              250
+#define DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR              10
+#define DEFAULT0_E2_BRB_MAC_FULL_XON_THR               50
 
 /* BRB thresholds for E2*/
 #define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE            170
 #define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE                      50
 #define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE          250
 
+/* BRB default for class 0 E3A0 */
+#define DEFAULT0_E3A0_BRB_MAC_PAUSE_XOFF_THR   290
+#define DEFAULT0_E3A0_BRB_MAC_PAUSE_XON_THR    410
+#define DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR    10
+#define DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR     50
+
 /* BRB thresholds for E3A0 */
 #define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE          290
 #define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE              0
 #define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE            50
 #define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE                410
 
+/* BRB default for E3B0 */
+#define DEFAULT0_E3B0_BRB_MAC_PAUSE_XOFF_THR   330
+#define DEFAULT0_E3B0_BRB_MAC_PAUSE_XON_THR    490
+#define DEFAULT0_E3B0_BRB_MAC_FULL_XOFF_THR    15
+#define DEFAULT0_E3B0_BRB_MAC_FULL_XON_THR     55
 
 /* BRB thresholds for E3B0 2 port mode*/
 #define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE               1025
 #define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE         50
 #define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE     384
 
-
 /* only for E3B0*/
 #define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR                       304
 #define PFC_E3B0_4P_BRB_FULL_LB_XON_THR                        384
-#define PFC_E3B0_4P_LB_GUART                           120
+#define PFC_E3B0_4P_LB_GUART           120
 
 #define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART            120
-#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST               80
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST       80
 
 #define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART            80
-#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST               120
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST       120
+
+/* Pause defines*/
+#define DEFAULT_E3B0_BRB_FULL_LB_XOFF_THR                      330
+#define DEFAULT_E3B0_BRB_FULL_LB_XON_THR                       490
+#define DEFAULT_E3B0_LB_GUART          40
+
+#define DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART           40
+#define DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART_HYST      0
+
+#define DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART           40
+#define DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART_HYST      0
 
+/* ETS defines*/
 #define DCBX_INVALID_COS                                       (0xFF)
 
 #define ETS_BW_LIMIT_CREDIT_UPPER_BOUND                (0x5000)
@@ -440,7 +466,7 @@ static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
        u32 min_w_val = 0;
        /* Calculate min_w_val.*/
        if (vars->link_up) {
-               if (SPEED_20000 == vars->line_speed)
+               if (vars->line_speed == SPEED_20000)
                        min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
                else
                        min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
@@ -490,7 +516,7 @@ static void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
        REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
                   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
 
-       if (0 == port) {
+       if (!port) {
                REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
                        credit_upper_bound);
                REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
@@ -584,7 +610,7 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
                   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
        REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
                   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
-       if (0 == port) {
+       if (!port) {
                REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
                REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
                REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
@@ -612,7 +638,7 @@ static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
        * In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
        * port mode port1 has COS0-2 that can be used for WFQ.
        */
-       if (0 == port) {
+       if (!port) {
                base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
                max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
        } else {
@@ -674,7 +700,7 @@ static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
        * In 2 port mode port0 has COS0-5 that can be used for WFQ.
        * In 4 port mode port1 has COS0-2 that can be used for WFQ.
        */
-       if (0 == port) {
+       if (!port) {
                base_weight = PBF_REG_COS0_WEIGHT_P0;
                max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
        } else {
@@ -846,34 +872,47 @@ static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
 ******************************************************************************/
 static int bnx2x_ets_e3b0_get_total_bw(
        const struct link_params *params,
-       const struct bnx2x_ets_params *ets_params,
+       struct bnx2x_ets_params *ets_params,
        u16 *total_bw)
 {
        struct bnx2x *bp = params->bp;
        u8 cos_idx = 0;
+       u8 is_bw_cos_exist = 0;
 
        *total_bw = 0 ;
+
        /* Calculate total BW requested */
        for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
-               if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
+               if (ets_params->cos[cos_idx].state == bnx2x_cos_state_bw) {
+                       is_bw_cos_exist = 1;
+                       if (!ets_params->cos[cos_idx].params.bw_params.bw) {
+                               DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
+                                                  "was set to 0\n");
+                               /*
+                                * This is to prevent a state when ramrods
+                                * can't be sent
+                               */
+                               ets_params->cos[cos_idx].params.bw_params.bw
+                                        = 1;
+                       }
                        *total_bw +=
                                ets_params->cos[cos_idx].params.bw_params.bw;
                }
        }
 
        /* Check total BW is valid */
-       if ((100 != *total_bw) || (0 == *total_bw)) {
-               if (0 == *total_bw) {
+       if ((is_bw_cos_exist == 1) && (*total_bw != 100)) {
+               if (*total_bw == 0) {
                        DP(NETIF_MSG_LINK,
-                          "bnx2x_ets_E3B0_config toatl BW shouldn't be 0\n");
+                          "bnx2x_ets_E3B0_config total BW shouldn't be 0\n");
                        return -EINVAL;
                }
                DP(NETIF_MSG_LINK,
-                  "bnx2x_ets_E3B0_config toatl BW should be 100\n");
-               /**
-               *   We can handle a case whre the BW isn't 100 this can happen
-               *   if the TC are joined.
-               */
+                  "bnx2x_ets_E3B0_config total BW should be 100\n");
+               /*
+                * We can handle a case whre the BW isn't 100 this can happen
+                * if the TC are joined.
+                */
        }
        return 0;
 }
@@ -904,7 +943,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
        const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
                DCBX_E3B0_MAX_NUM_COS_PORT0;
 
-       if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
+       if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) {
                DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
                                   "parameter There can't be two COS's with "
                                   "the same strict pri\n");
@@ -913,7 +952,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
 
        if (pri > max_num_of_cos) {
                DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
-                              "parameter Illegal strict priority\n");
+                  "parameter Illegal strict priority\n");
            return -EINVAL;
        }
 
@@ -995,8 +1034,8 @@ static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
 
        /* Set all the strict priority first */
        for (i = 0; i < max_num_of_cos; i++) {
-               if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
-                       if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
+               if (sp_pri_to_cos[i] != DCBX_INVALID_COS) {
+                       if (sp_pri_to_cos[i] >= DCBX_MAX_NUM_COS) {
                                DP(NETIF_MSG_LINK,
                                           "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
                                           "invalid cos entry\n");
@@ -1010,7 +1049,7 @@ static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
                            sp_pri_to_cos[i], pri_set);
                        pri_bitmask = 1 << sp_pri_to_cos[i];
                        /* COS is used remove it from bitmap.*/
-                       if (0 == (pri_bitmask & cos_bit_to_set)) {
+                       if (!(pri_bitmask & cos_bit_to_set)) {
                                DP(NETIF_MSG_LINK,
                                        "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
                                        "invalid There can't be two COS's with"
@@ -1072,7 +1111,7 @@ static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
 ******************************************************************************/
 int bnx2x_ets_e3b0_config(const struct link_params *params,
                         const struct link_vars *vars,
-                        const struct bnx2x_ets_params *ets_params)
+                        struct bnx2x_ets_params *ets_params)
 {
        struct bnx2x *bp = params->bp;
        int bnx2x_status = 0;
@@ -1105,15 +1144,15 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
        /* Prepare BW parameters*/
        bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
                                                   &total_bw);
-       if (0 != bnx2x_status) {
+       if (bnx2x_status) {
                DP(NETIF_MSG_LINK,
                   "bnx2x_ets_E3B0_config get_total_bw failed\n");
                return -EINVAL;
        }
 
-       /**
-        *  Upper bound is set according to current link speed (min_w_val
-        *  should be the same for upper bound and COS credit val).
+       /*
+        * Upper bound is set according to current link speed (min_w_val
+        * should be the same for upper bound and COS credit val).
         */
        bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
        bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
@@ -1122,7 +1161,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
        for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
                if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
                        cos_bw_bitmap |= (1 << cos_entry);
-                       /**
+                       /*
                         * The function also sets the BW in HW(not the mappin
                         * yet)
                         */
@@ -1146,7 +1185,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
                           "bnx2x_ets_e3b0_config cos state not valid\n");
                        return -EINVAL;
                }
-               if (0 != bnx2x_status) {
+               if (bnx2x_status) {
                        DP(NETIF_MSG_LINK,
                           "bnx2x_ets_e3b0_config set cos bw failed\n");
                        return bnx2x_status;
@@ -1157,7 +1196,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
        bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
                                                         sp_pri_to_cos);
 
-       if (0 != bnx2x_status) {
+       if (bnx2x_status) {
                DP(NETIF_MSG_LINK,
                   "bnx2x_ets_E3B0_config set_pri_cli_reg failed\n");
                return bnx2x_status;
@@ -1168,7 +1207,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
                                              cos_sp_bitmap,
                                              cos_bw_bitmap);
 
-       if (0 != bnx2x_status) {
+       if (bnx2x_status) {
                DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
                return bnx2x_status;
        }
@@ -1232,9 +1271,9 @@ void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
 
        DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
 
-       if ((0 == total_bw) ||
-           (0 == cos0_bw) ||
-           (0 == cos1_bw)) {
+       if ((!total_bw) ||
+           (!cos0_bw) ||
+           (!cos1_bw)) {
                DP(NETIF_MSG_LINK, "Total BW can't be zero\n");
                return;
        }
@@ -1290,7 +1329,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
         * dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
         * dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
         */
-       val = (0 == strict_cos) ? 0x2318 : 0x22E0;
+       val = (!strict_cos) ? 0x2318 : 0x22E0;
        REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
 
        return 0;
@@ -1298,7 +1337,6 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 /******************************************************************/
 /*                     PFC section                               */
 /******************************************************************/
-
 static void bnx2x_update_pfc_xmac(struct link_params *params,
                                  struct link_vars *vars,
                                  u8 is_lb)
@@ -1401,7 +1439,7 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
        if (!vars->link_up)
                return;
 
-       if (MAC_TYPE_EMAC == vars->mac_type) {
+       if (vars->mac_type == MAC_TYPE_EMAC) {
                DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
                bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
                                        pfc_frames_received);
@@ -1435,6 +1473,18 @@ static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
 
        udelay(40);
 }
+static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
+{
+       u32 port4mode_ovwr_val;
+       /* Check 4-port override enabled */
+       port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+       if (port4mode_ovwr_val & (1<<0)) {
+               /* Return 4-port mode override value */
+               return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
+       }
+       /* Return 4-port mode from input pin */
+       return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
+}
 
 static void bnx2x_emac_init(struct link_params *params,
                            struct link_vars *vars)
@@ -1601,31 +1651,18 @@ static void bnx2x_umac_enable(struct link_params *params,
 
 }
 
-static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
-{
-       u32 port4mode_ovwr_val;
-       /* Check 4-port override enabled */
-       port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
-       if (port4mode_ovwr_val & (1<<0)) {
-               /* Return 4-port mode override value */
-               return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
-       }
-       /* Return 4-port mode from input pin */
-       return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
-}
-
 /* Define the XMAC mode */
 static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
 {
        struct bnx2x *bp = params->bp;
        u32 is_port4mode = bnx2x_is_4_port_mode(bp);
 
-       /**
-       * In 4-port mode, need to set the mode only once, so if XMAC is
-       * already out of reset, it means the mode has already been set,
-       * and it must not* reset the XMAC again, since it controls both
-       * ports of the path
-       **/
+       /*
+        * In 4-port mode, need to set the mode only once, so if XMAC is
+        * already out of reset, it means the mode has already been set,
+        * and it must not* reset the XMAC again, since it controls both
+        * ports of the path
+        */
 
        if ((CHIP_NUM(bp) == CHIP_NUM_57840) &&
            (REG_RD(bp, MISC_REG_RESET_REG_2) &
@@ -1743,6 +1780,7 @@ static int bnx2x_xmac_enable(struct link_params *params,
 
        return 0;
 }
+
 static int bnx2x_emac_enable(struct link_params *params,
                             struct link_vars *vars, u8 lb)
 {
@@ -1999,7 +2037,6 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
        REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 }
 
-
 /* PFC BRB internal port configuration params */
 struct bnx2x_pfc_brb_threshold_val {
        u32 pause_xoff;
@@ -2009,6 +2046,8 @@ struct bnx2x_pfc_brb_threshold_val {
 };
 
 struct bnx2x_pfc_brb_e3b0_val {
+       u32 per_class_guaranty_mode;
+       u32 lb_guarantied_hyst;
        u32 full_lb_xoff_th;
        u32 full_lb_xon_threshold;
        u32 lb_guarantied;
@@ -2021,6 +2060,9 @@ struct bnx2x_pfc_brb_e3b0_val {
 struct bnx2x_pfc_brb_th_val {
        struct bnx2x_pfc_brb_threshold_val pauseable_th;
        struct bnx2x_pfc_brb_threshold_val non_pauseable_th;
+       struct bnx2x_pfc_brb_threshold_val default_class0;
+       struct bnx2x_pfc_brb_threshold_val default_class1;
+
 };
 static int bnx2x_pfc_brb_get_config_params(
                                struct link_params *params,
@@ -2028,140 +2070,200 @@ static int bnx2x_pfc_brb_get_config_params(
 {
        struct bnx2x *bp = params->bp;
        DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n");
+
+       config_val->default_class1.pause_xoff = 0;
+       config_val->default_class1.pause_xon = 0;
+       config_val->default_class1.full_xoff = 0;
+       config_val->default_class1.full_xon = 0;
+
        if (CHIP_IS_E2(bp)) {
+               /*  class0 defaults */
+               config_val->default_class0.pause_xoff =
+                       DEFAULT0_E2_BRB_MAC_PAUSE_XOFF_THR;
+               config_val->default_class0.pause_xon =
+                       DEFAULT0_E2_BRB_MAC_PAUSE_XON_THR;
+               config_val->default_class0.full_xoff =
+                       DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR;
+               config_val->default_class0.full_xon =
+                       DEFAULT0_E2_BRB_MAC_FULL_XON_THR;
+               /*  pause able*/
                config_val->pauseable_th.pause_xoff =
-                   PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+                       PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
                config_val->pauseable_th.pause_xon =
-                   PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
+                       PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
                config_val->pauseable_th.full_xoff =
-                   PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
+                       PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
                config_val->pauseable_th.full_xon =
-                   PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
+                       PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
                /* non pause able*/
                config_val->non_pauseable_th.pause_xoff =
-                   PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+                       PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
                config_val->non_pauseable_th.pause_xon =
-                   PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+                       PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
                config_val->non_pauseable_th.full_xoff =
-                   PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+                       PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
                config_val->non_pauseable_th.full_xon =
-                   PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+                       PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
        } else if (CHIP_IS_E3A0(bp)) {
+               /*  class0 defaults */
+               config_val->default_class0.pause_xoff =
+                       DEFAULT0_E3A0_BRB_MAC_PAUSE_XOFF_THR;
+               config_val->default_class0.pause_xon =
+                       DEFAULT0_E3A0_BRB_MAC_PAUSE_XON_THR;
+               config_val->default_class0.full_xoff =
+                       DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR;
+               config_val->default_class0.full_xon =
+                       DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR;
+               /*  pause able */
                config_val->pauseable_th.pause_xoff =
-                   PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+                       PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
                config_val->pauseable_th.pause_xon =
-                   PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
+                       PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
                config_val->pauseable_th.full_xoff =
-                   PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
+                       PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
                config_val->pauseable_th.full_xon =
-                   PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
+                       PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
                /* non pause able*/
                config_val->non_pauseable_th.pause_xoff =
-                   PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+                       PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
                config_val->non_pauseable_th.pause_xon =
-                   PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+                       PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
                config_val->non_pauseable_th.full_xoff =
-                   PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+                       PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
                config_val->non_pauseable_th.full_xon =
-                   PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+                       PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
        } else if (CHIP_IS_E3B0(bp)) {
+               /*  class0 defaults */
+               config_val->default_class0.pause_xoff =
+                       DEFAULT0_E3B0_BRB_MAC_PAUSE_XOFF_THR;
+               config_val->default_class0.pause_xon =
+                   DEFAULT0_E3B0_BRB_MAC_PAUSE_XON_THR;
+               config_val->default_class0.full_xoff =
+                   DEFAULT0_E3B0_BRB_MAC_FULL_XOFF_THR;
+               config_val->default_class0.full_xon =
+                   DEFAULT0_E3B0_BRB_MAC_FULL_XON_THR;
+
                if (params->phy[INT_PHY].flags &
                    FLAGS_4_PORT_MODE) {
                        config_val->pauseable_th.pause_xoff =
-                           PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+                               PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
                        config_val->pauseable_th.pause_xon =
-                           PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+                               PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
                        config_val->pauseable_th.full_xoff =
-                           PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+                               PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
                        config_val->pauseable_th.full_xon =
-                           PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
+                               PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
                        /* non pause able*/
                        config_val->non_pauseable_th.pause_xoff =
-                           PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+                       PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
                        config_val->non_pauseable_th.pause_xon =
-                           PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+                       PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
                        config_val->non_pauseable_th.full_xoff =
-                           PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+                       PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
                        config_val->non_pauseable_th.full_xon =
-                           PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-           } else {
-               config_val->pauseable_th.pause_xoff =
-                   PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
-               config_val->pauseable_th.pause_xon =
-                   PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
-               config_val->pauseable_th.full_xoff =
-                   PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
-               config_val->pauseable_th.full_xon =
-                       PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
-               /* non pause able*/
-               config_val->non_pauseable_th.pause_xoff =
-                   PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
-               config_val->non_pauseable_th.pause_xon =
-                   PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
-               config_val->non_pauseable_th.full_xoff =
-                   PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
-               config_val->non_pauseable_th.full_xon =
-                   PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-           }
+                       PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+               } else {
+                       config_val->pauseable_th.pause_xoff =
+                               PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+                       config_val->pauseable_th.pause_xon =
+                               PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+                       config_val->pauseable_th.full_xoff =
+                               PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+                       config_val->pauseable_th.full_xon =
+                               PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
+                       /* non pause able*/
+                       config_val->non_pauseable_th.pause_xoff =
+                               PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+                       config_val->non_pauseable_th.pause_xon =
+                               PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+                       config_val->non_pauseable_th.full_xoff =
+                               PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+                       config_val->non_pauseable_th.full_xon =
+                               PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+               }
        } else
            return -EINVAL;
 
        return 0;
 }
 
-
-static void bnx2x_pfc_brb_get_e3b0_config_params(struct link_params *params,
-                                                struct bnx2x_pfc_brb_e3b0_val
-                                                *e3b0_val,
-                                                u32 cos0_pauseable,
-                                                u32 cos1_pauseable)
+static void bnx2x_pfc_brb_get_e3b0_config_params(
+               struct link_params *params,
+               struct bnx2x_pfc_brb_e3b0_val
+               *e3b0_val,
+               struct bnx2x_nig_brb_pfc_port_params *pfc_params,
+               const u8 pfc_enabled)
 {
-       if (params->phy[INT_PHY].flags & FLAGS_4_PORT_MODE) {
+       if (pfc_enabled && pfc_params) {
+               e3b0_val->per_class_guaranty_mode = 1;
+               e3b0_val->lb_guarantied_hyst = 80;
+
+               if (params->phy[INT_PHY].flags &
+                   FLAGS_4_PORT_MODE) {
+                       e3b0_val->full_lb_xoff_th =
+                               PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
+                       e3b0_val->full_lb_xon_threshold =
+                               PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
+                       e3b0_val->lb_guarantied =
+                               PFC_E3B0_4P_LB_GUART;
+                       e3b0_val->mac_0_class_t_guarantied =
+                               PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
+                       e3b0_val->mac_0_class_t_guarantied_hyst =
+                               PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
+                       e3b0_val->mac_1_class_t_guarantied =
+                               PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
+                       e3b0_val->mac_1_class_t_guarantied_hyst =
+                               PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
+               } else {
+                       e3b0_val->full_lb_xoff_th =
+                               PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
+                       e3b0_val->full_lb_xon_threshold =
+                               PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
+                       e3b0_val->mac_0_class_t_guarantied_hyst =
+                               PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
+                       e3b0_val->mac_1_class_t_guarantied =
+                               PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
+                       e3b0_val->mac_1_class_t_guarantied_hyst =
+                               PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
+
+                       if (pfc_params->cos0_pauseable !=
+                               pfc_params->cos1_pauseable) {
+                               /* nonpauseable= Lossy + pauseable = Lossless*/
+                               e3b0_val->lb_guarantied =
+                                       PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
+                               e3b0_val->mac_0_class_t_guarantied =
+                              PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
+                       } else if (pfc_params->cos0_pauseable) {
+                               /* Lossless +Lossless*/
+                               e3b0_val->lb_guarantied =
+                                       PFC_E3B0_2P_PAUSE_LB_GUART;
+                               e3b0_val->mac_0_class_t_guarantied =
+                                  PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
+                       } else {
+                               /* Lossy +Lossy*/
+                               e3b0_val->lb_guarantied =
+                                       PFC_E3B0_2P_NON_PAUSE_LB_GUART;
+                               e3b0_val->mac_0_class_t_guarantied =
+                              PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
+                       }
+               }
+       } else {
+               e3b0_val->per_class_guaranty_mode = 0;
+               e3b0_val->lb_guarantied_hyst = 0;
                e3b0_val->full_lb_xoff_th =
-                   PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
+                       DEFAULT_E3B0_BRB_FULL_LB_XOFF_THR;
                e3b0_val->full_lb_xon_threshold =
-                   PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
+                       DEFAULT_E3B0_BRB_FULL_LB_XON_THR;
                e3b0_val->lb_guarantied =
-                   PFC_E3B0_4P_LB_GUART;
+                       DEFAULT_E3B0_LB_GUART;
                e3b0_val->mac_0_class_t_guarantied =
-                   PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
+                       DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART;
                e3b0_val->mac_0_class_t_guarantied_hyst =
-                   PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
+                       DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART_HYST;
                e3b0_val->mac_1_class_t_guarantied =
-                   PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
+                       DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART;
                e3b0_val->mac_1_class_t_guarantied_hyst =
-                   PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
-       } else {
-               e3b0_val->full_lb_xoff_th =
-                   PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
-               e3b0_val->full_lb_xon_threshold =
-                   PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
-               e3b0_val->mac_0_class_t_guarantied_hyst =
-                   PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
-               e3b0_val->mac_1_class_t_guarantied =
-                   PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
-               e3b0_val->mac_1_class_t_guarantied_hyst =
-                   PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
-
-               if (cos0_pauseable != cos1_pauseable) {
-                       /* nonpauseable= Lossy + pauseable = Lossless*/
-                       e3b0_val->lb_guarantied =
-                           PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
-                       e3b0_val->mac_0_class_t_guarantied =
-                           PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
-               } else if (cos0_pauseable) {
-                       /* Lossless +Lossless*/
-                       e3b0_val->lb_guarantied =
-                           PFC_E3B0_2P_PAUSE_LB_GUART;
-                       e3b0_val->mac_0_class_t_guarantied =
-                           PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
-               } else {
-                       /* Lossy +Lossy*/
-                       e3b0_val->lb_guarantied =
-                           PFC_E3B0_2P_NON_PAUSE_LB_GUART;
-                       e3b0_val->mac_0_class_t_guarantied =
-                           PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
-               }
+                       DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART_HYST;
        }
 }
 static int bnx2x_update_pfc_brb(struct link_params *params,
@@ -2172,23 +2274,28 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
        struct bnx2x *bp = params->bp;
        struct bnx2x_pfc_brb_th_val config_val = { {0} };
        struct bnx2x_pfc_brb_threshold_val *reg_th_config =
-           &config_val.pauseable_th;
+               &config_val.pauseable_th;
        struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
-       int set_pfc = params->feature_config_flags &
+       const int set_pfc = params->feature_config_flags &
                FEATURE_CONFIG_PFC_ENABLED;
+       const u8 pfc_enabled = (set_pfc && pfc_params);
        int bnx2x_status = 0;
        u8 port = params->port;
 
        /* default - pause configuration */
        reg_th_config = &config_val.pauseable_th;
        bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
-       if (0 != bnx2x_status)
+       if (bnx2x_status)
                return bnx2x_status;
 
-       if (set_pfc && pfc_params)
+       if (pfc_enabled) {
                /* First COS */
-               if (!pfc_params->cos0_pauseable)
+               if (pfc_params->cos0_pauseable)
+                       reg_th_config = &config_val.pauseable_th;
+               else
                        reg_th_config = &config_val.non_pauseable_th;
+       } else
+               reg_th_config = &config_val.default_class0;
        /*
         * The number of free blocks below which the pause signal to class 0
         * of MAC #n is asserted. n=0,1
@@ -2215,122 +2322,119 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
        REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
               BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon);
 
-       if (set_pfc && pfc_params) {
+       if (pfc_enabled) {
                /* Second COS */
                if (pfc_params->cos1_pauseable)
                        reg_th_config = &config_val.pauseable_th;
                else
                        reg_th_config = &config_val.non_pauseable_th;
+       } else
+               reg_th_config = &config_val.default_class1;
+       /*
+        * The number of free blocks below which the pause signal to
+        * class 1 of MAC #n is asserted. n=0,1
+        */
+       REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
+              BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
+              reg_th_config->pause_xoff);
+
+       /*
+        * The number of free blocks above which the pause signal to
+        * class 1 of MAC #n is de-asserted. n=0,1
+        */
+       REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
+              BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
+              reg_th_config->pause_xon);
+       /*
+        * The number of free blocks below which the full signal to
+        * class 1 of MAC #n is asserted. n=0,1
+        */
+       REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
+              BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
+              reg_th_config->full_xoff);
+       /*
+        * The number of free blocks above which the full signal to
+        * class 1 of MAC #n is de-asserted. n=0,1
+        */
+       REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
+              BRB1_REG_FULL_1_XON_THRESHOLD_0,
+              reg_th_config->full_xon);
+
+       if (CHIP_IS_E3B0(bp)) {
+               bnx2x_pfc_brb_get_e3b0_config_params(
+                       params,
+                       &e3b0_val,
+                       pfc_params,
+                       pfc_enabled);
+
+               REG_WR(bp, BRB1_REG_PER_CLASS_GUARANTY_MODE,
+                          e3b0_val.per_class_guaranty_mode);
+
                /*
-                * The number of free blocks below which the pause signal to
-                * class 1 of MAC #n is asserted. n=0,1
-               **/
-               REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
-                      BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
-                      reg_th_config->pause_xoff);
+                * The hysteresis on the guarantied buffer space for the Lb
+                * port before signaling XON.
+                */
+               REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST,
+                          e3b0_val.lb_guarantied_hyst);
+
                /*
-                * The number of free blocks above which the pause signal to
-                * class 1 of MAC #n is de-asserted. n=0,1
+                * The number of free blocks below which the full signal to the
+                * LB port is asserted.
                 */
-               REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
-                      BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
-                      reg_th_config->pause_xon);
+               REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
+                      e3b0_val.full_lb_xoff_th);
                /*
-                * The number of free blocks below which the full signal to
-                * class 1 of MAC #n is asserted. n=0,1
+                * The number of free blocks above which the full signal to the
+                * LB port is de-asserted.
                 */
-               REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
-                      BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
-                      reg_th_config->full_xoff);
+               REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
+                      e3b0_val.full_lb_xon_threshold);
                /*
-                * The number of free blocks above which the full signal to
-                * class 1 of MAC #n is de-asserted. n=0,1
+                * The number of blocks guarantied for the MAC #n port. n=0,1
                 */
-               REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
-                      BRB1_REG_FULL_1_XON_THRESHOLD_0,
-                      reg_th_config->full_xon);
 
+               /* The number of blocks guarantied for the LB port.*/
+               REG_WR(bp, BRB1_REG_LB_GUARANTIED,
+                      e3b0_val.lb_guarantied);
 
-               if (CHIP_IS_E3B0(bp)) {
-                       /*Should be done by init tool */
-                       /*
-                       * BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
-                       * reset value
-                       * 944
-                       */
-
-                       /**
-                        * The hysteresis on the guarantied buffer space for the Lb port
-                        * before signaling XON.
-                        **/
-                       REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, 80);
-
-                       bnx2x_pfc_brb_get_e3b0_config_params(
-                           params,
-                           &e3b0_val,
-                           pfc_params->cos0_pauseable,
-                           pfc_params->cos1_pauseable);
-                       /**
-                        * The number of free blocks below which the full signal to the
-                        * LB port is asserted.
-                       */
-                       REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
-                                  e3b0_val.full_lb_xoff_th);
-                       /**
-                        * The number of free blocks above which the full signal to the
-                        * LB port is de-asserted.
-                       */
-                       REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
-                                  e3b0_val.full_lb_xon_threshold);
-                       /**
-                       * The number of blocks guarantied for the MAC #n port. n=0,1
-                       */
-
-                       /*The number of blocks guarantied for the LB port.*/
-                       REG_WR(bp, BRB1_REG_LB_GUARANTIED,
-                              e3b0_val.lb_guarantied);
-
-                       /**
-                        * The number of blocks guarantied for the MAC #n port.
-                       */
-                       REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
-                                  2 * e3b0_val.mac_0_class_t_guarantied);
-                       REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
-                                  2 * e3b0_val.mac_1_class_t_guarantied);
-                       /**
-                        * The number of blocks guarantied for class #t in MAC0. t=0,1
-                       */
-                       REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
-                              e3b0_val.mac_0_class_t_guarantied);
-                       REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
-                              e3b0_val.mac_0_class_t_guarantied);
-                       /**
-                        * The hysteresis on the guarantied buffer space for class in
-                        * MAC0.  t=0,1
-                       */
-                       REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
-                              e3b0_val.mac_0_class_t_guarantied_hyst);
-                       REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
-                              e3b0_val.mac_0_class_t_guarantied_hyst);
-
-                       /**
-                        * The number of blocks guarantied for class #t in MAC1.t=0,1
-                       */
-                       REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
-                              e3b0_val.mac_1_class_t_guarantied);
-                       REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
-                              e3b0_val.mac_1_class_t_guarantied);
-                       /**
-                        * The hysteresis on the guarantied buffer space for class #t
-                       * in MAC1.  t=0,1
-                       */
-                       REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
-                              e3b0_val.mac_1_class_t_guarantied_hyst);
-                       REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
-                              e3b0_val.mac_1_class_t_guarantied_hyst);
-
-           }
+               /*
+                * The number of blocks guarantied for the MAC #n port.
+                */
+               REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
+                      2 * e3b0_val.mac_0_class_t_guarantied);
+               REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
+                      2 * e3b0_val.mac_1_class_t_guarantied);
+               /*
+                * The number of blocks guarantied for class #t in MAC0. t=0,1
+                */
+               REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
+                      e3b0_val.mac_0_class_t_guarantied);
+               REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
+                      e3b0_val.mac_0_class_t_guarantied);
+               /*
+                * The hysteresis on the guarantied buffer space for class in
+                * MAC0.  t=0,1
+                */
+               REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
+                      e3b0_val.mac_0_class_t_guarantied_hyst);
+               REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
+                      e3b0_val.mac_0_class_t_guarantied_hyst);
 
+               /*
+                * The number of blocks guarantied for class #t in MAC1.t=0,1
+                */
+               REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
+                      e3b0_val.mac_1_class_t_guarantied);
+               REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
+                      e3b0_val.mac_1_class_t_guarantied);
+               /*
+                * The hysteresis on the guarantied buffer space for class #t
+                * in MAC1.  t=0,1
+                */
+               REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
+                      e3b0_val.mac_1_class_t_guarantied_hyst);
+               REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
+                      e3b0_val.mac_1_class_t_guarantied_hyst);
        }
 
        return bnx2x_status;
@@ -2515,7 +2619,7 @@ int bnx2x_update_pfc(struct link_params *params,
 
        /* update BRB params */
        bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
-       if (0 != bnx2x_status)
+       if (bnx2x_status)
                return bnx2x_status;
 
        if (!vars->link_up)
@@ -2533,7 +2637,6 @@ int bnx2x_update_pfc(struct link_params *params,
                        bnx2x_emac_enable(params, vars, 0);
                        return bnx2x_status;
                }
-
                if (CHIP_IS_E2(bp))
                        bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
                else
@@ -3053,7 +3156,6 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
                DP(NETIF_MSG_LINK, "write phy register failed\n");
                netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
                rc = -EFAULT;
-
        } else {
                /* data */
                tmp = ((phy->addr << 21) | (devad << 16) | val |
@@ -3090,8 +3192,6 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
                               EMAC_MDIO_STATUS_10MB);
        return rc;
 }
-
-
 /******************************************************************/
 /*                     BSC access functions from E3              */
 /******************************************************************/
@@ -3339,7 +3439,7 @@ static void bnx2x_set_aer_mmd(struct link_params *params,
                aer_val = 0x3800 + offset - 1;
        else
                aer_val = 0x3800 + offset;
-       DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
+
        CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
                          MDIO_AER_BLOCK_AER_REG, aer_val);
 
@@ -3942,13 +4042,11 @@ static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
 
 static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
                                           struct link_params *params,
-                                          u8 fiber_mode)
+                                          u8 fiber_mode,
+                                          u8 always_autoneg)
 {
        struct bnx2x *bp = params->bp;
        u16 val16, digctrl_kx1, digctrl_kx2;
-       u8 lane;
-
-       lane = bnx2x_get_warpcore_lane(phy, params);
 
        /* Clear XFI clock comp in non-10G single lane mode. */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -3956,7 +4054,7 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
                         MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
 
-       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+       if (always_autoneg || phy->req_line_speed == SPEED_AUTO_NEG) {
                /* SGMII Autoneg */
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                                MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
@@ -3967,7 +4065,7 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
        } else {
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                                MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-               val16 &= 0xcfbf;
+               val16 &= 0xcebf;
                switch (phy->req_line_speed) {
                case SPEED_10:
                        break;
@@ -4043,9 +4141,7 @@ static void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                         MDIO_WC_REG_DIGITAL5_MISC6, &val);
 }
-
-
-       /* Clear SFI/XFI link settings registers */
+/* Clear SFI/XFI link settings registers */
 static void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
                                      struct link_params *params,
                                      u16 lane)
@@ -4250,7 +4346,7 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                vars->phy_flags |= PHY_SGMII_FLAG;
                DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
                bnx2x_warpcore_clear_regs(phy, params, lane);
-               bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
+               bnx2x_warpcore_set_sgmii_speed(phy, params, 0, 1);
        } else {
                switch (serdes_net_if) {
                case PORT_HW_CFG_NET_SERDES_IF_KR:
@@ -4278,7 +4374,8 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                                }
                                bnx2x_warpcore_set_sgmii_speed(phy,
                                                                params,
-                                                               fiber_mode);
+                                                               fiber_mode,
+                                                               0);
                        }
 
                        break;
@@ -4291,7 +4388,8 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                                bnx2x_warpcore_set_10G_XFI(phy, params, 0);
                        } else if (vars->line_speed == SPEED_1000) {
                                DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
-                               bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
+                               bnx2x_warpcore_set_sgmii_speed(
+                                               phy, params, 1, 0);
                        }
                        /* Issue Module detection */
                        if (bnx2x_is_sfp_module_plugged(phy, params))
@@ -4428,12 +4526,6 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
 
                /* Switch back to 4-copy registers */
                bnx2x_set_aer_mmd(params, phy);
-               /* Global loopback, not recommended. */
-               bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                               MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                               MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
-                               0x4000);
        } else {
                /* 10G & 20G */
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4450,25 +4542,14 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
 }
 
 
-void bnx2x_link_status_update(struct link_params *params,
-                             struct link_vars *vars)
+void bnx2x_sync_link(struct link_params *params,
+                          struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u8 link_10g_plus;
-       u8 port = params->port;
-       u32 sync_offset, media_types;
-       /* Update PHY configuration */
-       set_phy_vars(params, vars);
-
-       vars->link_status = REG_RD(bp, params->shmem_base +
-                                  offsetof(struct shmem_region,
-                                           port_mb[port].link_status));
-
-       vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-       vars->phy_flags = PHY_XGXS_FLAG;
        if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
                vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
-
+       vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
        if (vars->link_up) {
                DP(NETIF_MSG_LINK, "phy link up\n");
 
@@ -4563,7 +4644,23 @@ void bnx2x_link_status_update(struct link_params *params,
                if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
                        vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
        }
+}
+
+void bnx2x_link_status_update(struct link_params *params,
+                             struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u8 port = params->port;
+       u32 sync_offset, media_types;
+       /* Update PHY configuration */
+       set_phy_vars(params, vars);
+
+       vars->link_status = REG_RD(bp, params->shmem_base +
+                                  offsetof(struct shmem_region,
+                                           port_mb[port].link_status));
 
+       vars->phy_flags = PHY_XGXS_FLAG;
+       bnx2x_sync_link(params, vars);
        /* Sync media type */
        sync_offset = params->shmem_base +
                        offsetof(struct shmem_region,
@@ -4602,7 +4699,6 @@ void bnx2x_link_status_update(struct link_params *params,
                 vars->line_speed, vars->duplex, vars->flow_ctrl);
 }
 
-
 static void bnx2x_set_master_ln(struct link_params *params,
                                struct bnx2x_phy *phy)
 {
@@ -4676,11 +4772,8 @@ static void bnx2x_set_swap_lanes(struct link_params *params,
         *  Each two bits represents a lane number:
         *  No swap is 0123 => 0x1b no need to enable the swap
         */
-       u16 ser_lane, rx_lane_swap, tx_lane_swap;
+       u16 rx_lane_swap, tx_lane_swap;
 
-       ser_lane = ((params->lane_config &
-                    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-                   PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
        rx_lane_swap = ((params->lane_config &
                         PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
                        PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
@@ -5356,7 +5449,6 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
                                      struct link_params *params,
                                      struct link_vars *vars)
 {
-
        struct bnx2x *bp = params->bp;
 
        u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
@@ -5403,9 +5495,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
                                     struct link_params *params,
                                     struct link_vars *vars)
 {
-
        struct bnx2x *bp = params->bp;
-
        u8 lane;
        u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
        int rc = 0;
@@ -6678,7 +6768,6 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
        return rc;
 }
 
-
 /*****************************************************************************/
 /*                         External Phy section                             */
 /*****************************************************************************/
@@ -8103,7 +8192,15 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
                                    struct link_params *params)
 {
+       struct bnx2x *bp = params->bp;
        bnx2x_warpcore_power_module(params, phy, 0);
+       /* Put Warpcore in low power mode */
+       REG_WR(bp, MISC_REG_WC0_RESET, 0x0c0e);
+
+       /* Put LCPLL in low power mode */
+       REG_WR(bp, MISC_REG_LCPLL_E40_PWRDWN, 1);
+       REG_WR(bp, MISC_REG_LCPLL_E40_RESETB_ANA, 0);
+       REG_WR(bp, MISC_REG_LCPLL_E40_RESETB_DIG, 0);
 }
 
 static void bnx2x_power_sfp_module(struct link_params *params,
@@ -9040,13 +9137,13 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
                        DP(NETIF_MSG_LINK,
                           "8727 Power fault has been detected on port %d\n",
                           oc_port);
-                       netdev_err(bp->dev, "Error:  Power fault on Port %d has"
-                                           " been detected and the power to "
-                                           "that SFP+ module has been removed"
-                                           " to prevent failure of the card."
-                                           " Please remove the SFP+ module and"
-                                           " restart the system to clear this"
-                                           " error.\n",
+                       netdev_err(bp->dev, "Error: Power fault on Port %d has "
+                                           "been detected and the power to "
+                                           "that SFP+ module has been removed "
+                                           "to prevent failure of the card. "
+                                           "Please remove the SFP+ module and "
+                                           "restart the system to clear this "
+                                           "error.\n",
                         oc_port);
                        /* Disable all RX_ALARMs except for mod_abs */
                        bnx2x_cl45_write(bp, phy,
@@ -9228,7 +9325,7 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
                                struct bnx2x_phy *phy)
 {
-       u16 val;
+       u16 val, offset;
 
        /* PHYC_CTL_LED_CTL */
        bnx2x_cl45_read(bp, phy,
@@ -9263,14 +9360,22 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
                        MDIO_PMA_REG_8481_LED3_BLINK,
                        0);
 
-       bnx2x_cl45_read(bp, phy,
+       /* Configure the blink rate to ~15.9 Hz */
+       bnx2x_cl45_write(bp, phy,
                        MDIO_PMA_DEVAD,
-                       MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
-       val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
+                       MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
+                       MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ);
+
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+               offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
+       else
+               offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
 
+       bnx2x_cl45_read(bp, phy,
+                       MDIO_PMA_DEVAD, offset, &val);
+       val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
        bnx2x_cl45_write(bp, phy,
-                        MDIO_PMA_DEVAD,
-                        MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
+                        MDIO_PMA_DEVAD, offset, val);
 
        /* 'Interrupt Mask' */
        bnx2x_cl45_write(bp, phy,
@@ -9283,7 +9388,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                                       struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 autoneg_val, an_1000_val, an_10_100_val;
+       u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val;
        u16 tmp_req_line_speed;
 
        tmp_req_line_speed = phy->req_line_speed;
@@ -9378,6 +9483,8 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy,
                                 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
                                 (1<<15 | 1<<9 | 7<<0));
+               /* The PHY needs this set even for forced link. */
+               an_10_100_val |= (1<<8) | (1<<7);
                DP(NETIF_MSG_LINK, "Setting 100M force\n");
        }
        if ((phy->req_line_speed == SPEED_10) &&
@@ -9415,9 +9522,17 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                        DP(NETIF_MSG_LINK, "Advertising 10G\n");
                        /* Restart autoneg for 10G*/
 
+                       bnx2x_cl45_read(bp, phy,
+                                       MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+                                       &an_10g_val);
+                       bnx2x_cl45_write(bp, phy,
+                                        MDIO_AN_DEVAD,
+                                        MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+                                        an_10g_val | 0x1000);
                        bnx2x_cl45_write(bp, phy,
-                                MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
-                                0x3200);
+                                        MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
+                                        0x3200);
        } else
                bnx2x_cl45_write(bp, phy,
                                 MDIO_AN_DEVAD,
@@ -9449,74 +9564,95 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
        return bnx2x_848xx_cmn_config_init(phy, params, vars);
 }
 
-
-#define PHY84833_HDSHK_WAIT 300
-static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+#define PHY84833_CMDHDLR_WAIT 300
+#define PHY84833_CMDHDLR_MAX_ARGS 5
+static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
                                   struct link_params *params,
-                                  struct link_vars *vars)
+                  u16 fw_cmd,
+                  u16 cmd_args[])
 {
        u32 idx;
-       u32 pair_swap;
        u16 val;
-       u16 data;
        struct bnx2x *bp = params->bp;
-       /* Do pair swap */
-
-       /* Check for configuration. */
-       pair_swap = REG_RD(bp, params->shmem_base +
-                          offsetof(struct shmem_region,
-                       dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
-               PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
-
-       if (pair_swap == 0)
-               return 0;
-
-       data = (u16)pair_swap;
-
        /* Write CMD_OPEN_OVERRIDE to STATUS reg */
        bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                       MDIO_84833_TOP_CFG_SCRATCH_REG2,
-                       PHY84833_CMD_OPEN_OVERRIDE);
-       for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+                       MDIO_84833_CMD_HDLR_STATUS,
+                       PHY84833_STATUS_CMD_OPEN_OVERRIDE);
+       for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
                bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-               if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+                               MDIO_84833_CMD_HDLR_STATUS, &val);
+               if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
                        break;
                msleep(1);
        }
-       if (idx >= PHY84833_HDSHK_WAIT) {
-               DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
+       if (idx >= PHY84833_CMDHDLR_WAIT) {
+               DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
                return -EINVAL;
        }
 
+       /* Prepare argument(s) and issue command */
+       for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++) {
+               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+                               MDIO_84833_CMD_HDLR_DATA1 + idx,
+                               cmd_args[idx]);
+       }
        bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                       MDIO_84833_TOP_CFG_SCRATCH_REG4,
-                       data);
-       /* Issue pair swap command */
-       bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                       MDIO_84833_TOP_CFG_SCRATCH_REG0,
-                       PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
-       for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+                       MDIO_84833_CMD_HDLR_COMMAND, fw_cmd);
+       for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
                bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-               if ((val == PHY84833_CMD_COMPLETE_PASS) ||
-                       (val == PHY84833_CMD_COMPLETE_ERROR))
+                               MDIO_84833_CMD_HDLR_STATUS, &val);
+               if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
+                       (val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
                        break;
                msleep(1);
        }
-       if ((idx >= PHY84833_HDSHK_WAIT) ||
-               (val == PHY84833_CMD_COMPLETE_ERROR)) {
-               DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
+       if ((idx >= PHY84833_CMDHDLR_WAIT) ||
+               (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
+               DP(NETIF_MSG_LINK, "FW cmd failed.\n");
                return -EINVAL;
        }
+       /* Gather returning data */
+       for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++) {
+               bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+                               MDIO_84833_CMD_HDLR_DATA1 + idx,
+                               &cmd_args[idx]);
+       }
        bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                       MDIO_84833_TOP_CFG_SCRATCH_REG2,
-                       PHY84833_CMD_CLEAR_COMPLETE);
-       DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
+                       MDIO_84833_CMD_HDLR_STATUS,
+                       PHY84833_STATUS_CMD_CLEAR_COMPLETE);
        return 0;
 }
 
 
+static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+                                  struct link_params *params,
+                                  struct link_vars *vars)
+{
+       u32 pair_swap;
+       u16 data[PHY84833_CMDHDLR_MAX_ARGS];
+       int status;
+       struct bnx2x *bp = params->bp;
+
+       /* Check for configuration. */
+       pair_swap = REG_RD(bp, params->shmem_base +
+                          offsetof(struct shmem_region,
+                       dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
+               PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
+
+       if (pair_swap == 0)
+               return 0;
+
+       /* Only the second argument is used for this command */
+       data[1] = (u16)pair_swap;
+
+       status = bnx2x_84833_cmd_hdlr(phy, params,
+               PHY84833_CMD_SET_PAIR_SWAP, data);
+       if (status == 0)
+               DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]);
+
+       return status;
+}
+
 static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
                                      u32 shmem_base_path[],
                                      u32 chip_id)
@@ -9579,24 +9715,6 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
        return 0;
 }
 
-static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
-                                               u32 shmem_base_path[],
-                                               u32 chip_id)
-{
-       u8 reset_gpios;
-
-       reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
-
-       bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
-       udelay(10);
-       bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
-       msleep(800);
-       DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
-               reset_gpios);
-
-       return 0;
-}
-
 #define PHY84833_CONSTANT_LATENCY 1193
 static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                                   struct link_params *params,
@@ -9605,8 +9723,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u8 port, initialize = 1;
        u16 val;
-       u16 temp;
-       u32 actual_phy_selection, cms_enable, idx;
+       u32 actual_phy_selection, cms_enable;
+       u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
        int rc = 0;
 
        msleep(1);
@@ -9625,6 +9743,13 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy,
                                MDIO_PMA_DEVAD,
                                MDIO_PMA_REG_CTRL, 0x8000);
+       }
+
+       bnx2x_wait_reset_complete(bp, phy, params);
+
+       /* Wait for GPHY to come out of reset */
+       msleep(50);
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
                /* Bring PHY out of super isolate mode */
                bnx2x_cl45_read(bp, phy,
                                MDIO_CTL_DEVAD,
@@ -9633,26 +9758,19 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy,
                                MDIO_CTL_DEVAD,
                                MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
-       }
-
-       bnx2x_wait_reset_complete(bp, phy, params);
-
-       /* Wait for GPHY to come out of reset */
-       msleep(50);
-
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
                bnx2x_84833_pair_swap_cfg(phy, params, vars);
-
-       /*
-        * BCM84823 requires that XGXS links up first @ 10G for normal behavior
-        */
-       temp = vars->line_speed;
-       vars->line_speed = SPEED_10000;
-       bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
-       bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
-       vars->line_speed = temp;
-
-       /* Set dual-media configuration according to configuration */
+       } else {
+               /*
+                * BCM84823 requires that XGXS links up first @ 10G for normal
+                * behavior.
+                */
+               u16 temp;
+               temp = vars->line_speed;
+               vars->line_speed = SPEED_10000;
+               bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
+               bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
+               vars->line_speed = temp;
+       }
 
        bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
                        MDIO_CTL_REG_84823_MEDIA, &val);
@@ -9700,64 +9818,18 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 
        /* AutogrEEEn */
        if (params->feature_config_flags &
-               FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
-               /* Ensure that f/w is ready */
-               for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-                       bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-                                       MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-                       if (val == PHY84833_CMD_OPEN_FOR_CMDS)
-                               break;
-                       usleep_range(1000, 1000);
-               }
-               if (idx >= PHY84833_HDSHK_WAIT) {
-                       DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
-                       return -EINVAL;
-               }
-
-               /* Select EEE mode */
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_SCRATCH_REG3,
-                               0x2);
-
-               /* Set Idle and Latency */
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_SCRATCH_REG4,
-                               PHY84833_CONSTANT_LATENCY + 1);
-
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_DATA3_REG,
-                               PHY84833_CONSTANT_LATENCY + 1);
-
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_DATA4_REG,
-                               PHY84833_CONSTANT_LATENCY);
-
-               /* Send EEE instruction to command register */
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_SCRATCH_REG0,
-                               PHY84833_DIAG_CMD_SET_EEE_MODE);
-
-               /* Ensure that the command has completed */
-               for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-                       bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-                                       MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-                       if ((val == PHY84833_CMD_COMPLETE_PASS) ||
-                               (val == PHY84833_CMD_COMPLETE_ERROR))
-                               break;
-                       usleep_range(1000, 1000);
-               }
-               if ((idx >= PHY84833_HDSHK_WAIT) ||
-                       (val == PHY84833_CMD_COMPLETE_ERROR)) {
-                       DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
-                       return -EINVAL;
-               }
-
-               /* Reset command handler */
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                           MDIO_84833_TOP_CFG_SCRATCH_REG2,
-                           PHY84833_CMD_CLEAR_COMPLETE);
-       }
+               FEATURE_CONFIG_AUTOGREEEN_ENABLED)
+               cmd_args[0] = 0x2;
+       else
+               cmd_args[0] = 0x0;
 
+       cmd_args[1] = 0x0;
+       cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
+       cmd_args[3] = PHY84833_CONSTANT_LATENCY;
+       rc = bnx2x_84833_cmd_hdlr(phy, params,
+               PHY84833_CMD_SET_EEE_MODE, cmd_args);
+       if (rc != 0)
+               DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
        if (initialize)
                rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
        else
@@ -10144,8 +10216,10 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
        DP(NETIF_MSG_LINK, "54618SE cfg init\n");
        usleep_range(1000, 1000);
 
-       /* This works with E3 only, no need to check the chip
-          before determining the port. */
+       /*
+        * This works with E3 only, no need to check the chip
+        * before determining the port.
+        */
        port = params->port;
 
        cfg_pin = (REG_RD(bp, params->shmem_base +
@@ -11218,7 +11292,9 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                                       offsetof(struct shmem_region,
                        dev_info.port_feature_config[port].link_config)) &
                          PORT_FEATURE_CONNECTED_SWITCH_MASK);
-       chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
+       chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+               ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+
        DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
        if (USES_WARPCORE(bp)) {
                u32 serdes_net_if;
@@ -11397,6 +11473,10 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
                return -EINVAL;
        default:
                *phy = phy_null;
+               /* In case external PHY wasn't found */
+               if ((phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+                   (phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
+                       return -EINVAL;
                return 0;
        }
 
@@ -11570,7 +11650,7 @@ u32 bnx2x_phy_selection(struct link_params *params)
 
 int bnx2x_phy_probe(struct link_params *params)
 {
-       u8 phy_index, actual_phy_idx, link_cfg_idx;
+       u8 phy_index, actual_phy_idx;
        u32 phy_config_swapped, sync_offset, media_types;
        struct bnx2x *bp = params->bp;
        struct bnx2x_phy *phy;
@@ -11581,7 +11661,6 @@ int bnx2x_phy_probe(struct link_params *params)
 
        for (phy_index = INT_PHY; phy_index < MAX_PHYS;
              phy_index++) {
-               link_cfg_idx = LINK_CONFIG_IDX(phy_index);
                actual_phy_idx = phy_index;
                if (phy_config_swapped) {
                        if (phy_index == EXT_PHY1)
@@ -12247,6 +12326,63 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
        return 0;
 }
 
+static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
+                                               u32 shmem_base_path[],
+                                               u32 shmem2_base_path[],
+                                               u8 phy_index,
+                                               u32 chip_id)
+{
+       u8 reset_gpios;
+       struct bnx2x_phy phy;
+       u32 shmem_base, shmem2_base, cnt;
+       s8 port = 0;
+       u16 val;
+
+       reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
+       bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+       udelay(10);
+       bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+       DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
+               reset_gpios);
+       for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+               /* This PHY is for E2 and E3. */
+               shmem_base = shmem_base_path[port];
+               shmem2_base = shmem2_base_path[port];
+               /* Extract the ext phy address for the port */
+               if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+                                      0, &phy) !=
+                   0) {
+                       DP(NETIF_MSG_LINK, "populate_phy failed\n");
+                       return -EINVAL;
+               }
+
+               /* Wait for FW completing its initialization. */
+               for (cnt = 0; cnt < 1000; cnt++) {
+                       bnx2x_cl45_read(bp, &phy,
+                               MDIO_PMA_DEVAD,
+                               MDIO_PMA_REG_CTRL, &val);
+                       if (!(val & (1<<15)))
+                               break;
+                       msleep(1);
+               }
+               if (cnt >= 1000)
+                       DP(NETIF_MSG_LINK,
+                               "84833 Cmn reset timeout (%d)\n", port);
+
+               /* Put the port in super isolate mode. */
+               bnx2x_cl45_read(bp, &phy,
+                               MDIO_CTL_DEVAD,
+                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+               val |= MDIO_84833_SUPER_ISOLATE;
+               bnx2x_cl45_write(bp, &phy,
+                               MDIO_CTL_DEVAD,
+                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+       }
+
+       return 0;
+}
+
+
 static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
                                     u32 shmem2_base_path[], u8 phy_index,
                                     u32 ext_phy_type, u32 chip_id)
@@ -12281,7 +12417,9 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
                 * GPIO3's are linked, and so both need to be toggled
                 * to obtain required 2us pulse.
                 */
-               rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
+               rc = bnx2x_84833_common_init_phy(bp, shmem_base_path,
+                                               shmem2_base_path,
+                                               phy_index, chip_id);
                break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
                rc = -EINVAL;
index 2a46e633abe9c7992566c2e0fe0b89fa32816d8c..e02a68a7fb85f112953384bb96154547f8a8c2d5 100644 (file)
@@ -479,7 +479,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
 /*  Configure the COS to ETS according to BW and SP settings.*/
 int bnx2x_ets_e3b0_config(const struct link_params *params,
                         const struct link_vars *vars,
-                        const struct bnx2x_ets_params *ets_params);
+                        struct bnx2x_ets_params *ets_params);
 /* Read pfc statistic*/
 void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
                                                 u32 pfc_frames_sent[2],
index e58073ef33b47e5dc45708d794726a7a038470a2..44609de4e5dc59f7ecbe41d3ea8c0e01f17d837e 100644 (file)
 #define BRB1_REG_PAUSE_HIGH_THRESHOLD_1                         0x6007c
 /* [RW 10] Write client 0: Assert pause threshold. */
 #define BRB1_REG_PAUSE_LOW_THRESHOLD_0                          0x60068
-#define BRB1_REG_PAUSE_LOW_THRESHOLD_1                          0x6006c
-/* [R 24] The number of full blocks occupied by port. */
+/* [RW 1] Indicates if to use per-class guaranty mode (new mode) or per-MAC
+ * guaranty mode (backwards-compatible mode). 0=per-MAC guaranty mode (BC
+ * mode). 1=per-class guaranty mode (new mode). */
+#define BRB1_REG_PER_CLASS_GUARANTY_MODE                        0x60268
+/* [R 24] The number of full blocks occpied by port. */
 #define BRB1_REG_PORT_NUM_OCC_BLOCKS_0                          0x60094
 /* [RW 1] Reset the design by software. */
 #define BRB1_REG_SOFT_RESET                                     0x600dc
    register bits. */
 #define MISC_REG_LCPLL_CTRL_1                                   0xa2a4
 #define MISC_REG_LCPLL_CTRL_REG_2                               0xa2a8
+/* [RW 1] LCPLL power down. Global register. Active High. Reset on POR
+ * reset. */
+#define MISC_REG_LCPLL_E40_PWRDWN                               0xaa74
+/* [RW 1] LCPLL VCO reset. Global register. Active Low Reset on POR reset. */
+#define MISC_REG_LCPLL_E40_RESETB_ANA                           0xaa78
+/* [RW 1] LCPLL post-divider reset. Global register. Active Low Reset on POR
+ * reset. */
+#define MISC_REG_LCPLL_E40_RESETB_DIG                           0xaa7c
 /* [RW 4] Interrupt mask register #0 read/write */
 #define MISC_REG_MISC_INT_MASK                                  0xa388
 /* [RW 1] Parity mask register #0 read/write */
  * is compared to the value on ctrl_md_devad. Drives output
  * misc_xgxs0_phy_addr. Global register. */
 #define MISC_REG_WC0_CTRL_PHY_ADDR                              0xa9cc
+#define MISC_REG_WC0_RESET                                      0xac30
 /* [RW 2] XMAC Core port mode. Indicates the number of ports on the system
    side. This should be less than or equal to phy_port_mode; if some of the
    ports are not used. This enables reduction of frequency on the core side.
@@ -6823,11 +6835,13 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER       0x0000
 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER                0x0100
 #define MDIO_CTL_REG_84823_MEDIA_FIBER_1G                      0x1000
-#define MDIO_CTL_REG_84823_USER_CTRL_REG               0x4005
-#define MDIO_CTL_REG_84823_USER_CTRL_CMS               0x0080
-
-#define MDIO_PMA_REG_84823_CTL_LED_CTL_1               0xa8e3
-#define MDIO_PMA_REG_84823_LED3_STRETCH_EN             0x0080
+#define MDIO_CTL_REG_84823_USER_CTRL_REG                       0x4005
+#define MDIO_CTL_REG_84823_USER_CTRL_CMS                       0x0080
+#define MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH               0xa82b
+#define MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ       0x2f
+#define MDIO_PMA_REG_84823_CTL_LED_CTL_1                       0xa8e3
+#define MDIO_PMA_REG_84833_CTL_LED_CTL_1                       0xa8ec
+#define MDIO_PMA_REG_84823_LED3_STRETCH_EN                     0x0080
 
 /* BCM84833 only */
 #define MDIO_84833_TOP_CFG_XGPHY_STRAP1                        0x401a
@@ -6838,26 +6852,35 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_84833_TOP_CFG_SCRATCH_REG2                        0x4007
 #define MDIO_84833_TOP_CFG_SCRATCH_REG3                        0x4008
 #define MDIO_84833_TOP_CFG_SCRATCH_REG4                        0x4009
-#define MDIO_84833_TOP_CFG_DATA3_REG                   0x4011
-#define MDIO_84833_TOP_CFG_DATA4_REG                   0x4012
+#define MDIO_84833_TOP_CFG_SCRATCH_REG26               0x4037
+#define MDIO_84833_TOP_CFG_SCRATCH_REG27               0x4038
+#define MDIO_84833_TOP_CFG_SCRATCH_REG28               0x4039
+#define MDIO_84833_TOP_CFG_SCRATCH_REG29               0x403a
+#define MDIO_84833_TOP_CFG_SCRATCH_REG30               0x403b
+#define MDIO_84833_TOP_CFG_SCRATCH_REG31               0x403c
+#define MDIO_84833_CMD_HDLR_COMMAND    MDIO_84833_TOP_CFG_SCRATCH_REG0
+#define MDIO_84833_CMD_HDLR_STATUS     MDIO_84833_TOP_CFG_SCRATCH_REG26
+#define MDIO_84833_CMD_HDLR_DATA1      MDIO_84833_TOP_CFG_SCRATCH_REG27
+#define MDIO_84833_CMD_HDLR_DATA2      MDIO_84833_TOP_CFG_SCRATCH_REG28
+#define MDIO_84833_CMD_HDLR_DATA3      MDIO_84833_TOP_CFG_SCRATCH_REG29
+#define MDIO_84833_CMD_HDLR_DATA4      MDIO_84833_TOP_CFG_SCRATCH_REG30
+#define MDIO_84833_CMD_HDLR_DATA5      MDIO_84833_TOP_CFG_SCRATCH_REG31
 
 /* Mailbox command set used by 84833. */
-#define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE             0x2
+#define PHY84833_CMD_SET_PAIR_SWAP                     0x8001
+#define PHY84833_CMD_GET_EEE_MODE                      0x8008
+#define PHY84833_CMD_SET_EEE_MODE                      0x8009
 /* Mailbox status set used by 84833. */
-#define PHY84833_CMD_RECEIVED                          0x0001
-#define PHY84833_CMD_IN_PROGRESS                       0x0002
-#define PHY84833_CMD_COMPLETE_PASS                     0x0004
-#define PHY84833_CMD_COMPLETE_ERROR                    0x0008
-#define PHY84833_CMD_OPEN_FOR_CMDS                     0x0010
-#define PHY84833_CMD_SYSTEM_BOOT                       0x0020
-#define PHY84833_CMD_NOT_OPEN_FOR_CMDS                 0x0040
-#define PHY84833_CMD_CLEAR_COMPLETE                    0x0080
-#define PHY84833_CMD_OPEN_OVERRIDE                     0xa5a5
-
+#define PHY84833_STATUS_CMD_RECEIVED                   0x0001
+#define PHY84833_STATUS_CMD_IN_PROGRESS                        0x0002
+#define PHY84833_STATUS_CMD_COMPLETE_PASS              0x0004
+#define PHY84833_STATUS_CMD_COMPLETE_ERROR             0x0008
+#define PHY84833_STATUS_CMD_OPEN_FOR_CMDS              0x0010
+#define PHY84833_STATUS_CMD_SYSTEM_BOOT                        0x0020
+#define PHY84833_STATUS_CMD_NOT_OPEN_FOR_CMDS          0x0040
+#define PHY84833_STATUS_CMD_CLEAR_COMPLETE             0x0080
+#define PHY84833_STATUS_CMD_OPEN_OVERRIDE              0xa5a5
 
-/* 84833 F/W Feature Commands */
-#define PHY84833_DIAG_CMD_GET_EEE_MODE                 0x27
-#define PHY84833_DIAG_CMD_SET_EEE_MODE                 0x28
 
 /* Warpcore clause 45 addressing */
 #define MDIO_WC_DEVAD                                  0x3
index 0acb279dcf5cd6ff77f2bd3151a88ecb3c675a93..aa413d6551ad8be54d1c43282e527ef0242587d2 100644 (file)
@@ -7615,15 +7615,11 @@ static void tg3_restore_pci_state(struct tg3 *tp)
 
        pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
-               if (tg3_flag(tp, PCI_EXPRESS))
-                       pcie_set_readrq(tp->pdev, tp->pcie_readrq);
-               else {
-                       pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
-                                             tp->pci_cacheline_sz);
-                       pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
-                                             tp->pci_lat_timer);
-               }
+       if (!tg3_flag(tp, PCI_EXPRESS)) {
+               pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+                                     tp->pci_cacheline_sz);
+               pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                                     tp->pci_lat_timer);
        }
 
        /* Make sure PCI-X relaxed ordering bit is clear. */
@@ -7808,8 +7804,6 @@ static int tg3_chip_reset(struct tg3 *tp)
                                      pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
                                      val16);
 
-               pcie_set_readrq(tp->pdev, tp->pcie_readrq);
-
                /* Clear error status */
                pci_write_config_word(tp->pdev,
                                      pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA,
@@ -13988,9 +13982,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tg3_flag(tp, HW_TSO_1) ||
            tg3_flag(tp, HW_TSO_2) ||
            tg3_flag(tp, HW_TSO_3) ||
-           (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF)))
+           tp->fw_needed) {
+               /* For firmware TSO, assume ASF is disabled.
+                * We'll disable TSO later if we discover ASF
+                * is enabled in tg3_get_eeprom_hw_cfg().
+                */
                tg3_flag_set(tp, TSO_CAPABLE);
-       else {
+       else {
                tg3_flag_clear(tp, TSO_CAPABLE);
                tg3_flag_clear(tp, TSO_BUG);
                tp->fw_needed = NULL;
@@ -14049,12 +14047,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
                tg3_flag_set(tp, PCI_EXPRESS);
 
-               tp->pcie_readrq = 4096;
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
-                       tp->pcie_readrq = 2048;
-
-               pcie_set_readrq(tp->pdev, tp->pcie_readrq);
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) {
+                       int readrq = pcie_get_readrq(tp->pdev);
+                       if (readrq > 2048)
+                               pcie_set_readrq(tp->pdev, 2048);
+               }
 
                pci_read_config_word(tp->pdev,
                                     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
@@ -14266,6 +14263,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         */
        tg3_get_eeprom_hw_cfg(tp);
 
+       if (tp->fw_needed && tg3_flag(tp, ENABLE_ASF)) {
+               tg3_flag_clear(tp, TSO_CAPABLE);
+               tg3_flag_clear(tp, TSO_BUG);
+               tp->fw_needed = NULL;
+       }
+
        if (tg3_flag(tp, ENABLE_APE)) {
                /* Allow reads and writes to the
                 * APE register and memory space.
diff --git a/include/net/flow_keys.h b/include/net/flow_keys.h
new file mode 100644 (file)
index 0000000..e4cb285
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _NET_FLOW_KEYS_H
+#define _NET_FLOW_KEYS_H
+
+struct flow_keys {
+       __be32 src;
+       __be32 dst;
+       union {
+               __be32 ports;
+               __be16 port16[2];
+       };
+       u8 ip_proto;
+};
+
+extern bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
+#endif
index 3606d40aae623f1b0bcffaf71efadb0e19c44c30..c4ecc864020f4f3f84c88bafab64d5c3a1e3db34 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
-        gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
+        gen_stats.o gen_estimator.o net_namespace.o secure_seq.o flow_dissector.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
index 8afb244b205f6c11fc3f645b020c067b0b795def..962e3de25a35a00bfaa337ad0fa62354be957a9a 100644 (file)
 #include <linux/pci.h>
 #include <linux/inetdevice.h>
 #include <linux/cpu_rmap.h>
-#include <linux/if_tunnel.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_defs.h>
 #include <linux/net_tstamp.h>
 #include <linux/jump_label.h>
+#include <net/flow_keys.h>
 
 #include "net-sysfs.h"
 
@@ -2598,123 +2596,28 @@ static inline void ____napi_schedule(struct softnet_data *sd,
  */
 void __skb_get_rxhash(struct sk_buff *skb)
 {
-       int nhoff, hash = 0, poff;
-       const struct ipv6hdr *ip6;
-       const struct iphdr *ip;
-       const struct vlan_hdr *vlan;
-       u8 ip_proto;
-       u32 addr1, addr2;
-       u16 proto;
-       union {
-               u32 v32;
-               u16 v16[2];
-       } ports;
-
-       nhoff = skb_network_offset(skb);
-       proto = skb->protocol;
-
-again:
-       switch (proto) {
-       case __constant_htons(ETH_P_IP):
-ip:
-               if (!pskb_may_pull(skb, sizeof(*ip) + nhoff))
-                       goto done;
-
-               ip = (const struct iphdr *) (skb->data + nhoff);
-               if (ip_is_fragment(ip))
-                       ip_proto = 0;
-               else
-                       ip_proto = ip->protocol;
-               addr1 = (__force u32) ip->saddr;
-               addr2 = (__force u32) ip->daddr;
-               nhoff += ip->ihl * 4;
-               break;
-       case __constant_htons(ETH_P_IPV6):
-ipv6:
-               if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff))
-                       goto done;
-
-               ip6 = (const struct ipv6hdr *) (skb->data + nhoff);
-               ip_proto = ip6->nexthdr;
-               addr1 = (__force u32) ip6->saddr.s6_addr32[3];
-               addr2 = (__force u32) ip6->daddr.s6_addr32[3];
-               nhoff += 40;
-               break;
-       case __constant_htons(ETH_P_8021Q):
-               if (!pskb_may_pull(skb, sizeof(*vlan) + nhoff))
-                       goto done;
-               vlan = (const struct vlan_hdr *) (skb->data + nhoff);
-               proto = vlan->h_vlan_encapsulated_proto;
-               nhoff += sizeof(*vlan);
-               goto again;
-       case __constant_htons(ETH_P_PPP_SES):
-               if (!pskb_may_pull(skb, PPPOE_SES_HLEN + nhoff))
-                       goto done;
-               proto = *((__be16 *) (skb->data + nhoff +
-                                     sizeof(struct pppoe_hdr)));
-               nhoff += PPPOE_SES_HLEN;
-               switch (proto) {
-               case __constant_htons(PPP_IP):
-                       goto ip;
-               case __constant_htons(PPP_IPV6):
-                       goto ipv6;
-               default:
-                       goto done;
-               }
-       default:
-               goto done;
-       }
-
-       switch (ip_proto) {
-       case IPPROTO_GRE:
-               if (pskb_may_pull(skb, nhoff + 16)) {
-                       u8 *h = skb->data + nhoff;
-                       __be16 flags = *(__be16 *)h;
+       struct flow_keys keys;
+       u32 hash;
 
-                       /*
-                        * Only look inside GRE if version zero and no
-                        * routing
-                        */
-                       if (!(flags & (GRE_VERSION|GRE_ROUTING))) {
-                               proto = *(__be16 *)(h + 2);
-                               nhoff += 4;
-                               if (flags & GRE_CSUM)
-                                       nhoff += 4;
-                               if (flags & GRE_KEY)
-                                       nhoff += 4;
-                               if (flags & GRE_SEQ)
-                                       nhoff += 4;
-                               goto again;
-                       }
-               }
-               break;
-       case IPPROTO_IPIP:
-               goto again;
-       default:
-               break;
-       }
+       if (!skb_flow_dissect(skb, &keys))
+               return;
 
-       ports.v32 = 0;
-       poff = proto_ports_offset(ip_proto);
-       if (poff >= 0) {
-               nhoff += poff;
-               if (pskb_may_pull(skb, nhoff + 4)) {
-                       ports.v32 = * (__force u32 *) (skb->data + nhoff);
-                       if (ports.v16[1] < ports.v16[0])
-                               swap(ports.v16[0], ports.v16[1]);
-                       skb->l4_rxhash = 1;
-               }
+       if (keys.ports) {
+               if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0])
+                       swap(keys.port16[0], keys.port16[1]);
+               skb->l4_rxhash = 1;
        }
 
        /* get a consistent hash (same value on both flow directions) */
-       if (addr2 < addr1)
-               swap(addr1, addr2);
+       if ((__force u32)keys.dst < (__force u32)keys.src)
+               swap(keys.dst, keys.src);
 
-       hash = jhash_3words(addr1, addr2, ports.v32, hashrnd);
+       hash = jhash_3words((__force u32)keys.dst,
+                           (__force u32)keys.src,
+                           (__force u32)keys.ports, hashrnd);
        if (!hash)
                hash = 1;
 
-done:
        skb->rxhash = hash;
 }
 EXPORT_SYMBOL(__skb_get_rxhash);
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
new file mode 100644 (file)
index 0000000..f0516d9
--- /dev/null
@@ -0,0 +1,134 @@
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <linux/if_tunnel.h>
+#include <linux/if_pppox.h>
+#include <linux/ppp_defs.h>
+#include <net/flow_keys.h>
+
+
+bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow)
+{
+       int poff, nhoff = skb_network_offset(skb);
+       u8 ip_proto;
+       __be16 proto = skb->protocol;
+
+       memset(flow, 0, sizeof(*flow));
+
+again:
+       switch (proto) {
+       case __constant_htons(ETH_P_IP): {
+               const struct iphdr *iph;
+               struct iphdr _iph;
+ip:
+               iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+               if (!iph)
+                       return false;
+
+               if (ip_is_fragment(iph))
+                       ip_proto = 0;
+               else
+                       ip_proto = iph->protocol;
+               flow->src = iph->saddr;
+               flow->dst = iph->daddr;
+               nhoff += iph->ihl * 4;
+               break;
+       }
+       case __constant_htons(ETH_P_IPV6): {
+               const struct ipv6hdr *iph;
+               struct ipv6hdr _iph;
+ipv6:
+               iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+               if (!iph)
+                       return false;
+
+               ip_proto = iph->nexthdr;
+               flow->src = iph->saddr.s6_addr32[3];
+               flow->dst = iph->daddr.s6_addr32[3];
+               nhoff += sizeof(struct ipv6hdr);
+               break;
+       }
+       case __constant_htons(ETH_P_8021Q): {
+               const struct vlan_hdr *vlan;
+               struct vlan_hdr _vlan;
+
+               vlan = skb_header_pointer(skb, nhoff, sizeof(_vlan), &_vlan);
+               if (!vlan)
+                       return false;
+
+               proto = vlan->h_vlan_encapsulated_proto;
+               nhoff += sizeof(*vlan);
+               goto again;
+       }
+       case __constant_htons(ETH_P_PPP_SES): {
+               struct {
+                       struct pppoe_hdr hdr;
+                       __be16 proto;
+               } *hdr, _hdr;
+               hdr = skb_header_pointer(skb, nhoff, sizeof(_hdr), &_hdr);
+               if (!hdr)
+                       return false;
+               proto = hdr->proto;
+               nhoff += PPPOE_SES_HLEN;
+               switch (proto) {
+               case __constant_htons(PPP_IP):
+                       goto ip;
+               case __constant_htons(PPP_IPV6):
+                       goto ipv6;
+               default:
+                       return false;
+               }
+       }
+       default:
+               return false;
+       }
+
+       switch (ip_proto) {
+       case IPPROTO_GRE: {
+               struct gre_hdr {
+                       __be16 flags;
+                       __be16 proto;
+               } *hdr, _hdr;
+
+               hdr = skb_header_pointer(skb, nhoff, sizeof(_hdr), &_hdr);
+               if (!hdr)
+                       return false;
+               /*
+                * Only look inside GRE if version zero and no
+                * routing
+                */
+               if (!(hdr->flags & (GRE_VERSION|GRE_ROUTING))) {
+                       proto = hdr->proto;
+                       nhoff += 4;
+                       if (hdr->flags & GRE_CSUM)
+                               nhoff += 4;
+                       if (hdr->flags & GRE_KEY)
+                               nhoff += 4;
+                       if (hdr->flags & GRE_SEQ)
+                               nhoff += 4;
+                       goto again;
+               }
+               break;
+       }
+       case IPPROTO_IPIP:
+               goto again;
+       default:
+               break;
+       }
+
+       flow->ip_proto = ip_proto;
+       poff = proto_ports_offset(ip_proto);
+       if (poff >= 0) {
+               __be32 *ports, _ports;
+
+               nhoff += poff;
+               ports = skb_header_pointer(skb, nhoff, sizeof(_ports), &_ports);
+               if (ports)
+                       flow->ports = *ports;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL(skb_flow_dissect);
index 50c359645665a89e3f0b3b3174a53248a116969e..ecbc89a0436b8d25ff3d3cb75e20c21baa701ed3 100644 (file)
@@ -891,7 +891,7 @@ EXPORT_SYMBOL(tcp_sendpage);
 #define TCP_PAGE(sk)   (sk->sk_sndmsg_page)
 #define TCP_OFF(sk)    (sk->sk_sndmsg_off)
 
-static inline int select_size(const struct sock *sk, int sg)
+static inline int select_size(const struct sock *sk, bool sg)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        int tmp = tp->mss_cache;
@@ -917,9 +917,9 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct iovec *iov;
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *skb;
-       int iovlen, flags;
+       int iovlen, flags, err, copied;
        int mss_now, size_goal;
-       int sg, err, copied;
+       bool sg;
        long timeo;
 
        lock_sock(sk);
@@ -946,7 +946,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
                goto out_err;
 
-       sg = sk->sk_route_caps & NETIF_F_SG;
+       sg = !!(sk->sk_route_caps & NETIF_F_SG);
 
        while (--iovlen >= 0) {
                size_t seglen = iov->iov_len;
index 7b582300d051dcb81765f07714b4e9d16e056a6a..51ff19485e1218ec8eef3a051bbb3529c8ff8ad0 100644 (file)
@@ -26,6 +26,8 @@
 #include <net/pkt_cls.h>
 #include <net/ip.h>
 #include <net/route.h>
+#include <net/flow_keys.h>
+
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 #include <net/netfilter/nf_conntrack.h>
 #endif
@@ -66,134 +68,37 @@ static inline u32 addr_fold(void *addr)
        return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0);
 }
 
-static u32 flow_get_src(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_src(const struct sk_buff *skb, const struct flow_keys *flow)
 {
-       __be32 *data = NULL, hdata;
-
-       switch (skb->protocol) {
-       case htons(ETH_P_IP):
-               data = skb_header_pointer(skb,
-                                         nhoff + offsetof(struct iphdr,
-                                                          saddr),
-                                         4, &hdata);
-               break;
-       case htons(ETH_P_IPV6):
-               data = skb_header_pointer(skb,
-                                        nhoff + offsetof(struct ipv6hdr,
-                                                         saddr.s6_addr32[3]),
-                                        4, &hdata);
-               break;
-       }
-
-       if (data)
-               return ntohl(*data);
+       if (flow->src)
+               return ntohl(flow->src);
        return addr_fold(skb->sk);
 }
 
-static u32 flow_get_dst(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_dst(const struct sk_buff *skb, const struct flow_keys *flow)
 {
-       __be32 *data = NULL, hdata;
-
-       switch (skb->protocol) {
-       case htons(ETH_P_IP):
-               data = skb_header_pointer(skb,
-                                         nhoff + offsetof(struct iphdr,
-                                                          daddr),
-                                         4, &hdata);
-               break;
-       case htons(ETH_P_IPV6):
-               data = skb_header_pointer(skb,
-                                        nhoff + offsetof(struct ipv6hdr,
-                                                         daddr.s6_addr32[3]),
-                                        4, &hdata);
-               break;
-       }
-
-       if (data)
-               return ntohl(*data);
+       if (flow->dst)
+               return ntohl(flow->dst);
        return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
 }
 
-static u32 flow_get_proto(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_proto(const struct sk_buff *skb, const struct flow_keys *flow)
 {
-       __u8 *data = NULL, hdata;
-
-       switch (skb->protocol) {
-       case htons(ETH_P_IP):
-               data = skb_header_pointer(skb,
-                                         nhoff + offsetof(struct iphdr,
-                                                          protocol),
-                                         1, &hdata);
-               break;
-       case htons(ETH_P_IPV6):
-               data = skb_header_pointer(skb,
-                                        nhoff + offsetof(struct ipv6hdr,
-                                                         nexthdr),
-                                        1, &hdata);
-               break;
-       }
-       if (data)
-               return *data;
-       return 0;
+       return flow->ip_proto;
 }
 
-/* helper function to get either src or dst port */
-static __be16 *flow_get_proto_common(const struct sk_buff *skb, int nhoff,
-                                    __be16 *_port, int dst)
+static u32 flow_get_proto_src(const struct sk_buff *skb, const struct flow_keys *flow)
 {
-       __be16 *port = NULL;
-       int poff;
-
-       switch (skb->protocol) {
-       case htons(ETH_P_IP): {
-               struct iphdr *iph, _iph;
-
-               iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
-               if (!iph)
-                       break;
-               if (ip_is_fragment(iph))
-                       break;
-               poff = proto_ports_offset(iph->protocol);
-               if (poff >= 0)
-                       port = skb_header_pointer(skb,
-                                       nhoff + iph->ihl * 4 + poff + dst,
-                                       sizeof(*_port), _port);
-               break;
-       }
-       case htons(ETH_P_IPV6): {
-               struct ipv6hdr *iph, _iph;
-
-               iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
-               if (!iph)
-                       break;
-               poff = proto_ports_offset(iph->nexthdr);
-               if (poff >= 0)
-                       port = skb_header_pointer(skb,
-                                       nhoff + sizeof(*iph) + poff + dst,
-                                       sizeof(*_port), _port);
-               break;
-       }
-       }
-
-       return port;
-}
-
-static u32 flow_get_proto_src(const struct sk_buff *skb, int nhoff)
-{
-       __be16 _port, *port = flow_get_proto_common(skb, nhoff, &_port, 0);
-
-       if (port)
-               return ntohs(*port);
+       if (flow->ports)
+               return ntohs(flow->port16[0]);
 
        return addr_fold(skb->sk);
 }
 
-static u32 flow_get_proto_dst(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_proto_dst(const struct sk_buff *skb, const struct flow_keys *flow)
 {
-       __be16 _port, *port = flow_get_proto_common(skb, nhoff, &_port, 2);
-
-       if (port)
-               return ntohs(*port);
+       if (flow->ports)
+               return ntohs(flow->port16[1]);
 
        return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
 }
@@ -239,7 +144,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb)
 })
 #endif
 
-static u32 flow_get_nfct_src(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_nfct_src(const struct sk_buff *skb, const struct flow_keys *flow)
 {
        switch (skb->protocol) {
        case htons(ETH_P_IP):
@@ -248,10 +153,10 @@ static u32 flow_get_nfct_src(const struct sk_buff *skb, int nhoff)
                return ntohl(CTTUPLE(skb, src.u3.ip6[3]));
        }
 fallback:
-       return flow_get_src(skb, nhoff);
+       return flow_get_src(skb, flow);
 }
 
-static u32 flow_get_nfct_dst(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_nfct_dst(const struct sk_buff *skb, const struct flow_keys *flow)
 {
        switch (skb->protocol) {
        case htons(ETH_P_IP):
@@ -260,21 +165,21 @@ static u32 flow_get_nfct_dst(const struct sk_buff *skb, int nhoff)
                return ntohl(CTTUPLE(skb, dst.u3.ip6[3]));
        }
 fallback:
-       return flow_get_dst(skb, nhoff);
+       return flow_get_dst(skb, flow);
 }
 
-static u32 flow_get_nfct_proto_src(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_nfct_proto_src(const struct sk_buff *skb, const struct flow_keys *flow)
 {
        return ntohs(CTTUPLE(skb, src.u.all));
 fallback:
-       return flow_get_proto_src(skb, nhoff);
+       return flow_get_proto_src(skb, flow);
 }
 
-static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb, int nhoff)
+static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb, const struct flow_keys *flow)
 {
        return ntohs(CTTUPLE(skb, dst.u.all));
 fallback:
-       return flow_get_proto_dst(skb, nhoff);
+       return flow_get_proto_dst(skb, flow);
 }
 
 static u32 flow_get_rtclassid(const struct sk_buff *skb)
@@ -314,21 +219,19 @@ static u32 flow_get_rxhash(struct sk_buff *skb)
        return skb_get_rxhash(skb);
 }
 
-static u32 flow_key_get(struct sk_buff *skb, int key)
+static u32 flow_key_get(struct sk_buff *skb, int key, struct flow_keys *flow)
 {
-       int nhoff = skb_network_offset(skb);
-
        switch (key) {
        case FLOW_KEY_SRC:
-               return flow_get_src(skb, nhoff);
+               return flow_get_src(skb, flow);
        case FLOW_KEY_DST:
-               return flow_get_dst(skb, nhoff);
+               return flow_get_dst(skb, flow);
        case FLOW_KEY_PROTO:
-               return flow_get_proto(skb, nhoff);
+               return flow_get_proto(skb, flow);
        case FLOW_KEY_PROTO_SRC:
-               return flow_get_proto_src(skb, nhoff);
+               return flow_get_proto_src(skb, flow);
        case FLOW_KEY_PROTO_DST:
-               return flow_get_proto_dst(skb, nhoff);
+               return flow_get_proto_dst(skb, flow);
        case FLOW_KEY_IIF:
                return flow_get_iif(skb);
        case FLOW_KEY_PRIORITY:
@@ -338,13 +241,13 @@ static u32 flow_key_get(struct sk_buff *skb, int key)
        case FLOW_KEY_NFCT:
                return flow_get_nfct(skb);
        case FLOW_KEY_NFCT_SRC:
-               return flow_get_nfct_src(skb, nhoff);
+               return flow_get_nfct_src(skb, flow);
        case FLOW_KEY_NFCT_DST:
-               return flow_get_nfct_dst(skb, nhoff);
+               return flow_get_nfct_dst(skb, flow);
        case FLOW_KEY_NFCT_PROTO_SRC:
-               return flow_get_nfct_proto_src(skb, nhoff);
+               return flow_get_nfct_proto_src(skb, flow);
        case FLOW_KEY_NFCT_PROTO_DST:
-               return flow_get_nfct_proto_dst(skb, nhoff);
+               return flow_get_nfct_proto_dst(skb, flow);
        case FLOW_KEY_RTCLASSID:
                return flow_get_rtclassid(skb);
        case FLOW_KEY_SKUID:
@@ -361,6 +264,16 @@ static u32 flow_key_get(struct sk_buff *skb, int key)
        }
 }
 
+#define FLOW_KEYS_NEEDED ((1 << FLOW_KEY_SRC) |                \
+                         (1 << FLOW_KEY_DST) |                 \
+                         (1 << FLOW_KEY_PROTO) |               \
+                         (1 << FLOW_KEY_PROTO_SRC) |           \
+                         (1 << FLOW_KEY_PROTO_DST) |           \
+                         (1 << FLOW_KEY_NFCT_SRC) |            \
+                         (1 << FLOW_KEY_NFCT_DST) |            \
+                         (1 << FLOW_KEY_NFCT_PROTO_SRC) |      \
+                         (1 << FLOW_KEY_NFCT_PROTO_DST))
+
 static int flow_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                         struct tcf_result *res)
 {
@@ -373,16 +286,19 @@ static int flow_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 
        list_for_each_entry(f, &head->filters, list) {
                u32 keys[f->nkeys];
+               struct flow_keys flow_keys;
 
                if (!tcf_em_tree_match(skb, &f->ematches, NULL))
                        continue;
 
                keymask = f->keymask;
+               if (keymask & FLOW_KEYS_NEEDED)
+                       skb_flow_dissect(skb, &flow_keys);
 
                for (n = 0; n < f->nkeys; n++) {
                        key = ffs(keymask) - 1;
                        keymask &= ~(1 << key);
-                       keys[n] = flow_key_get(skb, key);
+                       keys[n] = flow_key_get(skb, key, &flow_keys);
                }
 
                if (f->mode == FLOW_MODE_HASH)
index e83c272c0325530edbedb86ac0c16c162e49fff0..96e42cae4c7a4580e753c41b9c4f1e5c29cabbcd 100644 (file)
@@ -26,6 +26,7 @@
 #include <net/ip.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
+#include <net/flow_keys.h>
 
 /*
  * SFB uses two B[l][n] : L x N arrays of bins (L levels, N bins per level)
@@ -286,6 +287,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        u32 minqlen = ~0;
        u32 r, slot, salt, sfbhash;
        int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+       struct flow_keys keys;
 
        if (unlikely(sch->q.qlen >= q->limit)) {
                sch->qstats.overlimits++;
@@ -309,13 +311,19 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                /* If using external classifiers, get result and record it. */
                if (!sfb_classify(skb, q, &ret, &salt))
                        goto other_drop;
+               keys.src = salt;
+               keys.dst = 0;
+               keys.ports = 0;
        } else {
-               salt = skb_get_rxhash(skb);
+               skb_flow_dissect(skb, &keys);
        }
 
        slot = q->slot;
 
-       sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
+       sfbhash = jhash_3words((__force u32)keys.dst,
+                              (__force u32)keys.src,
+                              (__force u32)keys.ports,
+                              q->bins[slot].perturbation);
        if (!sfbhash)
                sfbhash = 1;
        sfb_skb_cb(skb)->hashes[slot] = sfbhash;
@@ -347,7 +355,10 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (unlikely(p_min >= SFB_MAX_PROB)) {
                /* Inelastic flow */
                if (q->double_buffering) {
-                       sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
+                       sfbhash = jhash_3words((__force u32)keys.dst,
+                                              (__force u32)keys.src,
+                                              (__force u32)keys.ports,
+                                              q->bins[slot].perturbation);
                        if (!sfbhash)
                                sfbhash = 1;
                        sfb_skb_cb(skb)->hashes[slot] = sfbhash;