|
@@ -164,7 +164,8 @@
|
|
|
#define EDC_MODE_PASSIVE_DAC 0x0055
|
|
|
|
|
|
|
|
|
-
|
|
|
+#define ETS_BW_LIMIT_CREDIT_UPPER_BOUND (0x5000)
|
|
|
+#define ETS_BW_LIMIT_CREDIT_WEIGHT (0x5000)
|
|
|
/**********************************************************/
|
|
|
/* INTERFACE */
|
|
|
/**********************************************************/
|
|
@@ -205,6 +206,273 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
|
|
|
return val;
|
|
|
}
|
|
|
|
|
|
+/******************************************************************/
|
|
|
+/* ETS section */
|
|
|
+/******************************************************************/
|
|
|
+void bnx2x_ets_disabled(struct link_params *params)
|
|
|
+{
|
|
|
+ /* ETS disabled configuration*/
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+
|
|
|
+ DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
|
|
|
+
|
|
|
+ /**
|
|
|
+ * mapping between entry priority to client number (0,1,2 -debug and
|
|
|
+ * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
|
|
|
+ * 3bits client num.
|
|
|
+ * PRI4 | PRI3 | PRI2 | PRI1 | PRI0
|
|
|
+ * cos1-100 cos0-011 dbg1-010 dbg0-001 MCP-000
|
|
|
+ */
|
|
|
+
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
|
|
|
+ /**
|
|
|
+ * Bitmap of 5bits length. Each bit specifies whether the entry behaves
|
|
|
+ * as strict. Bits 0,1,2 - debug and management entries, 3 -
|
|
|
+ * COS0 entry, 4 - COS1 entry.
|
|
|
+ * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
|
|
|
+ * bit4 bit3 bit2 bit1 bit0
|
|
|
+ * MCP and debug are strict
|
|
|
+ */
|
|
|
+
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
|
|
|
+ /* defines which entries (clients) are subjected to WFQ arbitration */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
|
|
|
+ /**
|
|
|
+ * For strict priority entries defines the number of consecutive
|
|
|
+ * slots for the highest priority.
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
|
|
|
+ /**
|
|
|
+ * mapping between the CREDIT_WEIGHT registers and actual client
|
|
|
+ * numbers
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0);
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0);
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0);
|
|
|
+
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, 0);
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, 0);
|
|
|
+ REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
|
|
|
+ /* ETS mode disable */
|
|
|
+ REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
|
|
|
+ /**
|
|
|
+ * If ETS mode is enabled (there is no strict priority) defines a WFQ
|
|
|
+ * weight for COS0/COS1.
|
|
|
+ */
|
|
|
+ REG_WR(bp, PBF_REG_COS0_WEIGHT, 0x2710);
|
|
|
+ REG_WR(bp, PBF_REG_COS1_WEIGHT, 0x2710);
|
|
|
+ /* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter */
|
|
|
+ REG_WR(bp, PBF_REG_COS0_UPPER_BOUND, 0x989680);
|
|
|
+ REG_WR(bp, PBF_REG_COS1_UPPER_BOUND, 0x989680);
|
|
|
+ /* Defines the number of consecutive slots for the strict priority */
|
|
|
+ REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
|
|
|
+}
|
|
|
+
|
|
|
+void bnx2x_ets_bw_limit_common(const struct link_params *params)
|
|
|
+{
|
|
|
+ /* ETS disabled configuration */
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
|
|
|
+ /**
|
|
|
+ * defines which entries (clients) are subjected to WFQ arbitration
|
|
|
+ * COS0 0x8
|
|
|
+ * COS1 0x10
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
|
|
|
+ /**
|
|
|
+ * mapping between the ARB_CREDIT_WEIGHT registers and actual
|
|
|
+ * client numbers (WEIGHT_0 does not actually have to represent
|
|
|
+ * client 0)
|
|
|
+ * PRI4 | PRI3 | PRI2 | PRI1 | PRI0
|
|
|
+ * cos1-001 cos0-000 dbg1-100 dbg0-011 MCP-010
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
|
|
|
+
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
|
|
|
+ ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1,
|
|
|
+ ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
|
|
|
+
|
|
|
+ /* ETS mode enabled*/
|
|
|
+ REG_WR(bp, PBF_REG_ETS_ENABLED, 1);
|
|
|
+
|
|
|
+ /* Defines the number of consecutive slots for the strict priority */
|
|
|
+ REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
|
|
|
+ /**
|
|
|
+ * Bitmap of 5bits length. Each bit specifies whether the entry behaves
|
|
|
+ * as strict. Bits 0,1,2 - debug and management entries, 3 - COS0
|
|
|
+ * entry, 4 - COS1 entry.
|
|
|
+ * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
|
|
|
+ * bit4 bit3 bit2 bit1 bit0
|
|
|
+ * MCP and debug are strict
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
|
|
|
+
|
|
|
+ /* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
|
|
|
+ REG_WR(bp, PBF_REG_COS0_UPPER_BOUND,
|
|
|
+ ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
|
|
|
+ REG_WR(bp, PBF_REG_COS1_UPPER_BOUND,
|
|
|
+ ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
|
|
|
+}
|
|
|
+
|
|
|
+void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
|
|
|
+ const u32 cos1_bw)
|
|
|
+{
|
|
|
+ /* ETS disabled configuration*/
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ const u32 total_bw = cos0_bw + cos1_bw;
|
|
|
+ u32 cos0_credit_weight = 0;
|
|
|
+ u32 cos1_credit_weight = 0;
|
|
|
+
|
|
|
+ DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
|
|
|
+
|
|
|
+ if ((0 == total_bw) ||
|
|
|
+ (0 == cos0_bw) ||
|
|
|
+ (0 == cos1_bw)) {
|
|
|
+ DP(NETIF_MSG_LINK,
|
|
|
+ "bnx2x_ets_bw_limit: Total BW can't be zero\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cos0_credit_weight = (cos0_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
|
|
|
+ total_bw;
|
|
|
+ cos1_credit_weight = (cos1_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
|
|
|
+ total_bw;
|
|
|
+
|
|
|
+ bnx2x_ets_bw_limit_common(params);
|
|
|
+
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, cos0_credit_weight);
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, cos1_credit_weight);
|
|
|
+
|
|
|
+ REG_WR(bp, PBF_REG_COS0_WEIGHT, cos0_credit_weight);
|
|
|
+ REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
|
|
|
+}
|
|
|
+
|
|
|
+u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
|
|
|
+{
|
|
|
+ /* ETS disabled configuration*/
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ u32 val = 0;
|
|
|
+
|
|
|
+ if ((1 < strict_cos) && (NULL == params))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ DP(NETIF_MSG_LINK, "ETS enabled strict configuration\n");
|
|
|
+ /**
|
|
|
+ * Bitmap of 5bits length. Each bit specifies whether the entry behaves
|
|
|
+ * as strict. Bits 0,1,2 - debug and management entries,
|
|
|
+ * 3 - COS0 entry, 4 - COS1 entry.
|
|
|
+ * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
|
|
|
+ * bit4 bit3 bit2 bit1 bit0
|
|
|
+ * MCP and debug are strict
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
|
|
|
+ /**
|
|
|
+ * For strict priority entries defines the number of consecutive slots
|
|
|
+ * for the highest priority.
|
|
|
+ */
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
|
|
|
+ /* ETS mode disable */
|
|
|
+ REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
|
|
|
+ /* Defines the number of consecutive slots for the strict priority */
|
|
|
+ REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0x100);
|
|
|
+
|
|
|
+ /* Defines the number of consecutive slots for the strict priority */
|
|
|
+ REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * mapping between entry priority to client number (0,1,2 -debug and
|
|
|
+ * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
|
|
|
+ * 3bits client num.
|
|
|
+ * PRI4 | PRI3 | PRI2 | PRI1 | PRI0
|
|
|
+ * 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;
|
|
|
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+/******************************************************************/
|
|
|
+/* ETS section */
|
|
|
+/******************************************************************/
|
|
|
+
|
|
|
+static void bnx2x_bmac2_get_pfc_stat(struct link_params *params,
|
|
|
+ u32 pfc_frames_sent[2],
|
|
|
+ u32 pfc_frames_received[2])
|
|
|
+{
|
|
|
+ /* Read pfc statistic */
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
|
|
|
+ NIG_REG_INGRESS_BMAC0_MEM;
|
|
|
+
|
|
|
+ DP(NETIF_MSG_LINK, "pfc statistic read from BMAC\n");
|
|
|
+
|
|
|
+ REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_STAT_GTPP,
|
|
|
+ pfc_frames_sent, 2);
|
|
|
+
|
|
|
+ REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_STAT_GRPP,
|
|
|
+ pfc_frames_received, 2);
|
|
|
+
|
|
|
+}
|
|
|
+static void bnx2x_emac_get_pfc_stat(struct link_params *params,
|
|
|
+ u32 pfc_frames_sent[2],
|
|
|
+ u32 pfc_frames_received[2])
|
|
|
+{
|
|
|
+ /* Read pfc statistic */
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ u32 emac_base = params->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
|
|
|
+ u32 val_xon = 0;
|
|
|
+ u32 val_xoff = 0;
|
|
|
+
|
|
|
+ DP(NETIF_MSG_LINK, "pfc statistic read from EMAC\n");
|
|
|
+
|
|
|
+ /* PFC received frames */
|
|
|
+ val_xoff = REG_RD(bp, emac_base +
|
|
|
+ EMAC_REG_RX_PFC_STATS_XOFF_RCVD);
|
|
|
+ val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT;
|
|
|
+ val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_RCVD);
|
|
|
+ val_xon &= EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT;
|
|
|
+
|
|
|
+ pfc_frames_received[0] = val_xon + val_xoff;
|
|
|
+
|
|
|
+ /* PFC received sent */
|
|
|
+ val_xoff = REG_RD(bp, emac_base +
|
|
|
+ EMAC_REG_RX_PFC_STATS_XOFF_SENT);
|
|
|
+ val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT;
|
|
|
+ val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_SENT);
|
|
|
+ val_xon &= EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT;
|
|
|
+
|
|
|
+ pfc_frames_sent[0] = val_xon + val_xoff;
|
|
|
+}
|
|
|
+
|
|
|
+void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
|
|
|
+ u32 pfc_frames_sent[2],
|
|
|
+ u32 pfc_frames_received[2])
|
|
|
+{
|
|
|
+ /* Read pfc statistic */
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ u32 val = 0;
|
|
|
+ DP(NETIF_MSG_LINK, "pfc statistic\n");
|
|
|
+
|
|
|
+ if (!vars->link_up)
|
|
|
+ return;
|
|
|
+
|
|
|
+ val = REG_RD(bp, MISC_REG_RESET_REG_2);
|
|
|
+ if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
|
|
|
+ == 0) {
|
|
|
+ DP(NETIF_MSG_LINK, "About to read stats from EMAC\n");
|
|
|
+ bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
|
|
|
+ pfc_frames_received);
|
|
|
+ } else {
|
|
|
+ DP(NETIF_MSG_LINK, "About to read stats from BMAC\n");
|
|
|
+ bnx2x_bmac2_get_pfc_stat(params, pfc_frames_sent,
|
|
|
+ pfc_frames_received);
|
|
|
+ }
|
|
|
+}
|
|
|
+/******************************************************************/
|
|
|
+/* MAC/PBF section */
|
|
|
+/******************************************************************/
|
|
|
static void bnx2x_emac_init(struct link_params *params,
|
|
|
struct link_vars *vars)
|
|
|
{
|
|
@@ -315,24 +583,55 @@ static u8 bnx2x_emac_enable(struct link_params *params,
|
|
|
/* pause enable/disable */
|
|
|
bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
|
|
|
EMAC_RX_MODE_FLOW_EN);
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
|
|
|
- bnx2x_bits_en(bp, emac_base +
|
|
|
- EMAC_REG_EMAC_RX_MODE,
|
|
|
- EMAC_RX_MODE_FLOW_EN);
|
|
|
|
|
|
bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
|
|
|
- (EMAC_TX_MODE_EXT_PAUSE_EN |
|
|
|
- EMAC_TX_MODE_FLOW_EN));
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
|
|
|
- bnx2x_bits_en(bp, emac_base +
|
|
|
- EMAC_REG_EMAC_TX_MODE,
|
|
|
- (EMAC_TX_MODE_EXT_PAUSE_EN |
|
|
|
- EMAC_TX_MODE_FLOW_EN));
|
|
|
+ (EMAC_TX_MODE_EXT_PAUSE_EN |
|
|
|
+ EMAC_TX_MODE_FLOW_EN));
|
|
|
+ if (!(params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED)) {
|
|
|
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
|
|
|
+ bnx2x_bits_en(bp, emac_base +
|
|
|
+ EMAC_REG_EMAC_RX_MODE,
|
|
|
+ EMAC_RX_MODE_FLOW_EN);
|
|
|
+
|
|
|
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
|
|
|
+ bnx2x_bits_en(bp, emac_base +
|
|
|
+ EMAC_REG_EMAC_TX_MODE,
|
|
|
+ (EMAC_TX_MODE_EXT_PAUSE_EN |
|
|
|
+ EMAC_TX_MODE_FLOW_EN));
|
|
|
+ } else
|
|
|
+ bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
|
|
|
+ EMAC_TX_MODE_FLOW_EN);
|
|
|
}
|
|
|
|
|
|
/* KEEP_VLAN_TAG, promiscuous */
|
|
|
val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
|
|
|
val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Setting this bit causes MAC control frames (except for pause
|
|
|
+ * frames) to be passed on for processing. This setting has no
|
|
|
+ * affect on the operation of the pause frames. This bit effects
|
|
|
+ * all packets regardless of RX Parser packet sorting logic.
|
|
|
+ * Turn the PFC off to make sure we are in Xon state before
|
|
|
+ * enabling it.
|
|
|
+ */
|
|
|
+ EMAC_WR(bp, EMAC_REG_RX_PFC_MODE, 0);
|
|
|
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
|
|
|
+ DP(NETIF_MSG_LINK, "PFC is enabled\n");
|
|
|
+ /* Enable PFC again */
|
|
|
+ EMAC_WR(bp, EMAC_REG_RX_PFC_MODE,
|
|
|
+ EMAC_REG_RX_PFC_MODE_RX_EN |
|
|
|
+ EMAC_REG_RX_PFC_MODE_TX_EN |
|
|
|
+ EMAC_REG_RX_PFC_MODE_PRIORITIES);
|
|
|
+
|
|
|
+ EMAC_WR(bp, EMAC_REG_RX_PFC_PARAM,
|
|
|
+ ((0x0101 <<
|
|
|
+ EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT) |
|
|
|
+ (0x00ff <<
|
|
|
+ EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT)));
|
|
|
+ val |= EMAC_RX_MODE_KEEP_MAC_CONTROL;
|
|
|
+ }
|
|
|
EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
|
|
|
|
|
|
/* Set Loopback */
|
|
@@ -362,7 +661,9 @@ static u8 bnx2x_emac_enable(struct link_params *params,
|
|
|
/* enable the NIG in/out to the emac */
|
|
|
REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
|
|
|
val = 0;
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
|
|
|
+ if ((params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED) ||
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
|
|
|
val = 1;
|
|
|
|
|
|
REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
|
|
@@ -383,9 +684,38 @@ static u8 bnx2x_emac_enable(struct link_params *params,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void bnx2x_update_bmac2(struct link_params *params,
|
|
|
- struct link_vars *vars,
|
|
|
- u8 is_lb)
|
|
|
+static void bnx2x_update_pfc_bmac1(struct link_params *params,
|
|
|
+ struct link_vars *vars)
|
|
|
+{
|
|
|
+ u32 wb_data[2];
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
|
|
|
+ NIG_REG_INGRESS_BMAC0_MEM;
|
|
|
+
|
|
|
+ u32 val = 0x14;
|
|
|
+ if ((!(params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED)) &&
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
|
|
|
+ /* Enable BigMAC to react on received Pause packets */
|
|
|
+ val |= (1<<5);
|
|
|
+ wb_data[0] = val;
|
|
|
+ wb_data[1] = 0;
|
|
|
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2);
|
|
|
+
|
|
|
+ /* tx control */
|
|
|
+ val = 0xc0;
|
|
|
+ if (!(params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED) &&
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
|
|
|
+ val |= 0x800000;
|
|
|
+ wb_data[0] = val;
|
|
|
+ wb_data[1] = 0;
|
|
|
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2);
|
|
|
+}
|
|
|
+
|
|
|
+static void bnx2x_update_pfc_bmac2(struct link_params *params,
|
|
|
+ struct link_vars *vars,
|
|
|
+ u8 is_lb)
|
|
|
{
|
|
|
/*
|
|
|
* Set rx control: Strip CRC and enable BigMAC to relay
|
|
@@ -397,7 +727,9 @@ static void bnx2x_update_bmac2(struct link_params *params,
|
|
|
NIG_REG_INGRESS_BMAC0_MEM;
|
|
|
u32 val = 0x14;
|
|
|
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
|
|
|
+ if ((!(params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED)) &&
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
|
|
|
/* Enable BigMAC to react on received Pause packets */
|
|
|
val |= (1<<5);
|
|
|
wb_data[0] = val;
|
|
@@ -408,14 +740,47 @@ static void bnx2x_update_bmac2(struct link_params *params,
|
|
|
|
|
|
/* Tx control */
|
|
|
val = 0xc0;
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
|
|
|
+ if (!(params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED) &&
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
|
|
|
val |= 0x800000;
|
|
|
wb_data[0] = val;
|
|
|
wb_data[1] = 0;
|
|
|
- REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL,
|
|
|
- wb_data, 2);
|
|
|
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL, wb_data, 2);
|
|
|
+
|
|
|
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
|
|
|
+ DP(NETIF_MSG_LINK, "PFC is enabled\n");
|
|
|
+ /* Enable PFC RX & TX & STATS and set 8 COS */
|
|
|
+ wb_data[0] = 0x0;
|
|
|
+ wb_data[0] |= (1<<0); /* RX */
|
|
|
+ wb_data[0] |= (1<<1); /* TX */
|
|
|
+ wb_data[0] |= (1<<2); /* Force initial Xon */
|
|
|
+ wb_data[0] |= (1<<3); /* 8 cos */
|
|
|
+ wb_data[0] |= (1<<5); /* STATS */
|
|
|
+ wb_data[1] = 0;
|
|
|
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL,
|
|
|
+ wb_data, 2);
|
|
|
+ /* Clear the force Xon */
|
|
|
+ wb_data[0] &= ~(1<<2);
|
|
|
+ } else {
|
|
|
+ DP(NETIF_MSG_LINK, "PFC is disabled\n");
|
|
|
+ /* disable PFC RX & TX & STATS and set 8 COS */
|
|
|
+ wb_data[0] = 0x8;
|
|
|
+ wb_data[1] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
|
|
|
|
|
|
+ /**
|
|
|
+ * Set Time (based unit is 512 bit time) between automatic
|
|
|
+ * re-sending of PP packets amd enable automatic re-send of
|
|
|
+ * Per-Priroity Packet as long as pp_gen is asserted and
|
|
|
+ * pp_disable is low.
|
|
|
+ */
|
|
|
val = 0x8000;
|
|
|
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
|
|
|
+ val |= (1<<16); /* enable automatic re-send */
|
|
|
+
|
|
|
wb_data[0] = val;
|
|
|
wb_data[1] = 0;
|
|
|
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
|
|
@@ -427,6 +792,9 @@ static void bnx2x_update_bmac2(struct link_params *params,
|
|
|
val |= 0x4; /* Local loopback */
|
|
|
DP(NETIF_MSG_LINK, "enable bmac loopback\n");
|
|
|
}
|
|
|
+ /* When PFC enabled, Pass pause frames towards the NIG. */
|
|
|
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
|
|
|
+ val |= ((1<<6)|(1<<5));
|
|
|
|
|
|
wb_data[0] = val;
|
|
|
wb_data[1] = 0;
|
|
@@ -434,6 +802,239 @@ static void bnx2x_update_bmac2(struct link_params *params,
|
|
|
wb_data, 2);
|
|
|
}
|
|
|
|
|
|
+static void bnx2x_update_pfc_brb(struct link_params *params,
|
|
|
+ struct link_vars *vars,
|
|
|
+ struct bnx2x_nig_brb_pfc_port_params *pfc_params)
|
|
|
+{
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ int set_pfc = params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED;
|
|
|
+
|
|
|
+ /* default - pause configuration */
|
|
|
+ u32 pause_xoff_th = PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
|
|
|
+ u32 pause_xon_th = PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
|
|
|
+ u32 full_xoff_th = PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
|
|
|
+ u32 full_xon_th = PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
|
|
|
+
|
|
|
+ if (set_pfc && pfc_params)
|
|
|
+ /* First COS */
|
|
|
+ if (!pfc_params->cos0_pauseable) {
|
|
|
+ pause_xoff_th =
|
|
|
+ PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ pause_xon_th =
|
|
|
+ PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ full_xoff_th =
|
|
|
+ PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ full_xon_th =
|
|
|
+ PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ }
|
|
|
+ /* The number of free blocks below which the pause signal to class 0
|
|
|
+ of MAC #n is asserted. n=0,1 */
|
|
|
+ REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
|
|
|
+ /* The number of free blocks above which the pause signal to class 0
|
|
|
+ of MAC #n is de-asserted. n=0,1 */
|
|
|
+ REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
|
|
|
+ /* The number of free blocks below which the full signal to class 0
|
|
|
+ of MAC #n is asserted. n=0,1 */
|
|
|
+ REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
|
|
|
+ /* The number of free blocks above which the full signal to class 0
|
|
|
+ of MAC #n is de-asserted. n=0,1 */
|
|
|
+ REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
|
|
|
+
|
|
|
+ if (set_pfc && pfc_params) {
|
|
|
+ /* Second COS */
|
|
|
+ if (pfc_params->cos1_pauseable) {
|
|
|
+ pause_xoff_th =
|
|
|
+ PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
|
|
|
+ pause_xon_th =
|
|
|
+ PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
|
|
|
+ full_xoff_th =
|
|
|
+ PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
|
|
|
+ full_xon_th =
|
|
|
+ PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
|
|
|
+ } else {
|
|
|
+ pause_xoff_th =
|
|
|
+ PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ pause_xon_th =
|
|
|
+ PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ full_xoff_th =
|
|
|
+ PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ full_xon_th =
|
|
|
+ PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * The number of free blocks below which the pause signal to
|
|
|
+ * class 1 of MAC #n is asserted. n=0,1
|
|
|
+ **/
|
|
|
+ REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
|
|
|
+ /**
|
|
|
+ * 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, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
|
|
|
+ /**
|
|
|
+ * The number of free blocks below which the full signal to
|
|
|
+ * class 1 of MAC #n is asserted. n=0,1
|
|
|
+ **/
|
|
|
+ REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
|
|
|
+ /**
|
|
|
+ * 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, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void bnx2x_update_pfc_nig(struct link_params *params,
|
|
|
+ struct link_vars *vars,
|
|
|
+ struct bnx2x_nig_brb_pfc_port_params *nig_params)
|
|
|
+{
|
|
|
+ u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
|
|
|
+ u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
|
|
|
+ u32 pkt_priority_to_cos = 0;
|
|
|
+ u32 val;
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+ int port = params->port;
|
|
|
+ int set_pfc = params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED;
|
|
|
+ DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
|
|
|
+
|
|
|
+ /**
|
|
|
+ * When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
|
|
|
+ * MAC control frames (that are not pause packets)
|
|
|
+ * will be forwarded to the XCM.
|
|
|
+ */
|
|
|
+ xcm_mask = REG_RD(bp,
|
|
|
+ port ? NIG_REG_LLH1_XCM_MASK :
|
|
|
+ NIG_REG_LLH0_XCM_MASK);
|
|
|
+ /**
|
|
|
+ * nig params will override non PFC params, since it's possible to
|
|
|
+ * do transition from PFC to SAFC
|
|
|
+ */
|
|
|
+ if (set_pfc) {
|
|
|
+ pause_enable = 0;
|
|
|
+ llfc_out_en = 0;
|
|
|
+ llfc_enable = 0;
|
|
|
+ ppp_enable = 1;
|
|
|
+ xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
|
|
|
+ NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
|
|
|
+ xcm0_out_en = 0;
|
|
|
+ p0_hwpfc_enable = 1;
|
|
|
+ } else {
|
|
|
+ if (nig_params) {
|
|
|
+ llfc_out_en = nig_params->llfc_out_en;
|
|
|
+ llfc_enable = nig_params->llfc_enable;
|
|
|
+ pause_enable = nig_params->pause_enable;
|
|
|
+ } else /*defaul non PFC mode - PAUSE */
|
|
|
+ pause_enable = 1;
|
|
|
+
|
|
|
+ xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
|
|
|
+ NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
|
|
|
+ xcm0_out_en = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
|
|
|
+ NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
|
|
|
+ REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
|
|
|
+ NIG_REG_LLFC_ENABLE_0, llfc_enable);
|
|
|
+ REG_WR(bp, port ? NIG_REG_PAUSE_ENABLE_1 :
|
|
|
+ NIG_REG_PAUSE_ENABLE_0, pause_enable);
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_PPP_ENABLE_1 :
|
|
|
+ NIG_REG_PPP_ENABLE_0, ppp_enable);
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_LLH1_XCM_MASK :
|
|
|
+ NIG_REG_LLH0_XCM_MASK, xcm_mask);
|
|
|
+
|
|
|
+ REG_WR(bp, NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
|
|
|
+
|
|
|
+ /* output enable for RX_XCM # IF */
|
|
|
+ REG_WR(bp, NIG_REG_XCM0_OUT_EN, xcm0_out_en);
|
|
|
+
|
|
|
+ /* HW PFC TX enable */
|
|
|
+ REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
|
|
|
+
|
|
|
+ /* 0x2 = BMAC, 0x1= EMAC */
|
|
|
+ switch (vars->mac_type) {
|
|
|
+ case MAC_TYPE_EMAC:
|
|
|
+ val = 1;
|
|
|
+ break;
|
|
|
+ case MAC_TYPE_BMAC:
|
|
|
+ val = 0;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ val = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT, val);
|
|
|
+
|
|
|
+ if (nig_params) {
|
|
|
+ pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_P1_RX_COS0_PRIORITY_MASK :
|
|
|
+ NIG_REG_P0_RX_COS0_PRIORITY_MASK,
|
|
|
+ nig_params->rx_cos0_priority_mask);
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_P1_RX_COS1_PRIORITY_MASK :
|
|
|
+ NIG_REG_P0_RX_COS1_PRIORITY_MASK,
|
|
|
+ nig_params->rx_cos1_priority_mask);
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
|
|
|
+ NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
|
|
|
+ nig_params->llfc_high_priority_classes);
|
|
|
+
|
|
|
+ REG_WR(bp, port ? NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 :
|
|
|
+ NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0,
|
|
|
+ nig_params->llfc_low_priority_classes);
|
|
|
+ }
|
|
|
+ REG_WR(bp, port ? NIG_REG_P1_PKT_PRIORITY_TO_COS :
|
|
|
+ NIG_REG_P0_PKT_PRIORITY_TO_COS,
|
|
|
+ pkt_priority_to_cos);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void bnx2x_update_pfc(struct link_params *params,
|
|
|
+ struct link_vars *vars,
|
|
|
+ struct bnx2x_nig_brb_pfc_port_params *pfc_params)
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * The PFC and pause are orthogonal to one another, meaning when
|
|
|
+ * PFC is enabled, the pause are disabled, and when PFC is
|
|
|
+ * disabled, pause are set according to the pause result.
|
|
|
+ */
|
|
|
+ u32 val;
|
|
|
+ struct bnx2x *bp = params->bp;
|
|
|
+
|
|
|
+ /* update NIG params */
|
|
|
+ bnx2x_update_pfc_nig(params, vars, pfc_params);
|
|
|
+
|
|
|
+ /* update BRB params */
|
|
|
+ bnx2x_update_pfc_brb(params, vars, pfc_params);
|
|
|
+
|
|
|
+ if (!vars->link_up)
|
|
|
+ return;
|
|
|
+
|
|
|
+ val = REG_RD(bp, MISC_REG_RESET_REG_2);
|
|
|
+ if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
|
|
|
+ == 0) {
|
|
|
+ DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
|
|
|
+ bnx2x_emac_enable(params, vars, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
|
|
|
+ if (CHIP_IS_E2(bp))
|
|
|
+ bnx2x_update_pfc_bmac2(params, vars, 0);
|
|
|
+ else
|
|
|
+ bnx2x_update_pfc_bmac1(params, vars);
|
|
|
+
|
|
|
+ val = 0;
|
|
|
+ if ((params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED) ||
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
|
|
|
+ val = 1;
|
|
|
+ REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
|
|
|
+}
|
|
|
|
|
|
static u8 bnx2x_bmac1_enable(struct link_params *params,
|
|
|
struct link_vars *vars,
|
|
@@ -465,15 +1066,6 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
|
|
|
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
|
|
|
wb_data, 2);
|
|
|
|
|
|
- /* tx control */
|
|
|
- val = 0xc0;
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
|
|
|
- val |= 0x800000;
|
|
|
- wb_data[0] = val;
|
|
|
- wb_data[1] = 0;
|
|
|
- REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
|
|
|
- wb_data, 2);
|
|
|
-
|
|
|
/* mac control */
|
|
|
val = 0x3;
|
|
|
if (is_lb) {
|
|
@@ -491,14 +1083,7 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
|
|
|
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
|
|
|
wb_data, 2);
|
|
|
|
|
|
- /* rx control set to don't strip crc */
|
|
|
- val = 0x14;
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
|
|
|
- val |= 0x20;
|
|
|
- wb_data[0] = val;
|
|
|
- wb_data[1] = 0;
|
|
|
- REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
|
|
|
- wb_data, 2);
|
|
|
+ bnx2x_update_pfc_bmac1(params, vars);
|
|
|
|
|
|
/* set tx mtu */
|
|
|
wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
|
|
@@ -595,7 +1180,7 @@ static u8 bnx2x_bmac2_enable(struct link_params *params,
|
|
|
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE,
|
|
|
wb_data, 2);
|
|
|
udelay(30);
|
|
|
- bnx2x_update_bmac2(params, vars, is_lb);
|
|
|
+ bnx2x_update_pfc_bmac2(params, vars, is_lb);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -627,7 +1212,9 @@ static u8 bnx2x_bmac_enable(struct link_params *params,
|
|
|
REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
|
|
|
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
|
|
|
val = 0;
|
|
|
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
|
|
|
+ if ((params->feature_config_flags &
|
|
|
+ FEATURE_CONFIG_PFC_ENABLED) ||
|
|
|
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
|
|
|
val = 1;
|
|
|
REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
|
|
|
REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
|