commit b140dd528a9bde60e2b7489d8c9a383c6cb4ab6f
parent b32c618782c368946eb83329fe0f667f7d76e4ae
Author: Broadcom SDK Release <sdk.releases@broadcom.com>
Date: Wed, 15 Jan 2020 18:59:39 -0800
SDK-177793: 1. added WB variable "an400gRemotePause" for storing remote pause...
Devices: 56980_A0,56980_B0
Module: PortMod
Symptom:
When advertising pause, the pause settings are not being properly
programmed in the MAC after auto negotiation completes.
1. added WB variable "an400gRemotePause" for storing remote pause value;
2. updated pm8x50_port_autoneg_ability_remote_get() to set remote
abilities when 400G AN is resolved; 3. updated
pm8x50_port_phy_link_up_event() to update resolved pause settings for
400g AN;
Diffstat:
1 file changed, 148 insertions(+), 16 deletions(-)
diff --git a/sdk-6.5.16/src/soc/portmod/pms/pm8x50.c b/sdk-6.5.16/src/soc/portmod/pms/pm8x50.c
@@ -37,7 +37,7 @@
/* Warmboot variable defines - start */
-#define PM8x50_WB_BUFFER_VERSION (3)
+#define PM8x50_WB_BUFFER_VERSION (4)
#define PORTMOD_THREAD_INTERVAL_1s 1000000
#define TIMEOUT_COUNT_400G_AN 10
@@ -231,6 +231,30 @@
pm_info->wb_vars_ids[anWaitlinkCount],\
an_wait_link_count)
+#define PM8x50_BER_WAR_ENABLE_SET(unit, pm_info, is_ber_war_enable, port_index) \
+ SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \
+ pm_info->wb_vars_ids[isBerWarEnable], &is_ber_war_enable, port_index)
+
+#define PM8x50_BER_WAR_STATE_SET(unit, pm_info, ber_war_state, port_index) \
+ SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \
+ pm_info->wb_vars_ids[berWarState], &ber_war_state, port_index)
+
+#define PM8x50_BER_WAR_WAIT_COUNT_SET(unit, pm_info, ber_war_wait_count, port_index) \
+ SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \
+ pm_info->wb_vars_ids[berWarWaitCount], &ber_war_wait_count, port_index)
+
+#define PM8x50_IS_CORE_FLEXE_CONFIGURED_SET(unit, pm_info, is_core_flexe_configured) \
+ SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, \
+ pm_info->wb_vars_ids[coreisFlexeConfigured], \
+ &is_core_flexe_configured)
+
+#define PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, an_400g_remote_pause, port_index) \
+ SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \
+ pm_info->wb_vars_ids[an400gRemotePause], &an_400g_remote_pause, port_index)
+#define PM8x50_400G_AN_REMOTE_PAUSE_GET(unit, pm_info, an_400g_remote_pause, port_index) \
+ SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, \
+ pm_info->wb_vars_ids[an400gRemotePause], an_400g_remote_pause, port_index)
+
typedef enum pm8x50_wb_vars{
isCoreInitialized,
isActive,
@@ -259,6 +283,11 @@ typedef enum pm8x50_wb_vars{
anState400g, /* 400G an state */
anWaitlinkCount, /* 400G wait for link up count */
portIsPcsBypassed,
+ isBerWarEnable, /* Currently not supported */
+ berWarState, /* Currently not supported */
+ berWarWaitCount, /* Currently not supported */
+ coreisFlexeConfigured, /* Currently not supported */
+ an400gRemotePause, /* 400G AN Remote PAUSE value */
}pm8x50_wb_vars_t;
typedef enum pm8x50_port_soft_reset_mode{
@@ -321,6 +350,9 @@ typedef enum pm8x50_port_soft_reset_mode{
#define SPEED_CTRL_SPEED_ID_CLEAR 0xffc0
#define SPEED_ID_400G 0xa
+#define AN_X4_LP_BASE1r_REG 0xc1d3
+#define AN_LP_BASE1r_PAGE_PAUSE_MASK 0x3
+#define AN_LP_BASE1r_PAGE_PAUSE_OFFSET 0xA
STATIC portmod_ucode_buf_t pm8x50_ucode_buf[SOC_MAX_NUM_DEVICES] = {{NULL, 0}};
STATIC portmod_ucode_buf_t pm8x50_ucode_buf_2nd[SOC_MAX_NUM_DEVICES] = {{NULL, 0}};
@@ -335,6 +367,12 @@ typedef enum pm8x50_port_400g_an_state_e {
PM8X50_PORT_AN_STATE_COUNT
} pm8x50_port_400g_an_state_t;
+/*
+ * 200G and 400G BER monitoring workaround state
+ */
+typedef enum pm8x50_port_ber_war_state_e {
+ PM8X50_PORT_BER_WAR_STATE_COUNT = 4
+} pm8x50_port_ber_war_state_t;
/*
* Entries of the force speed ability table; each entry specifies a
@@ -781,12 +819,13 @@ int _pm8x50_400g_an_workaround(int unit, int port, pm_info_t pm_info, int* is_do
{
portmod_access_get_params_t params;
phymod_phy_access_t phy_access;
- uint32_t serdes_reg_val, wait_link_count;
+ uint32_t serdes_reg_val, wait_link_count, base_reg_val, remote_pause;
int nof_phys;
pm8x50_port_400g_an_state_t an_state;
phymod_autoneg_control_t an_control;
char* state_string = "\n";
-
+ int port_index;
+ uint32 bitmap;
SOC_INIT_FUNC_DEFS;
@@ -814,6 +853,14 @@ int _pm8x50_400g_an_workaround(int unit, int port, pm_info_t pm_info, int* is_do
if (serdes_reg_val & AN_X4_SW_CTRL_STS_AN_COMPLETE_MASK) {
int phy_acc;
uint32 reg_val;
+
+ /* get port index */
+ _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
+ _SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, AN_X4_LP_BASE1r_REG, &base_reg_val));
+ /* store remote pause value */
+ remote_pause = (base_reg_val >> AN_LP_BASE1r_PAGE_PAUSE_OFFSET) & AN_LP_BASE1r_PAGE_PAUSE_MASK;
+ _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, remote_pause, port_index));
+
/* need to move one to the next stage */
/* disable AN_Cl73 and AN_CL73BAM */
_SOC_IF_ERR_EXIT(phymod_phy_reg_read(&phy_access, AN_X4_CL73_CFG_REG, &serdes_reg_val));
@@ -1449,6 +1496,7 @@ int portmod_pm8x50_wb_upgrade_func(int unit, void *arg, int recovered_version,
int port_is_pcs_bypased;
int i, ts_enable_port_count;
uint32 fec_null, timesync_enable;
+ int remote_pause;
SOC_INIT_FUNC_DEFS;
@@ -1478,6 +1526,14 @@ int portmod_pm8x50_wb_upgrade_func(int unit, void *arg, int recovered_version,
PM8x50_PORT_IS_PCS_BYPASSED_SET(unit, pm_info, port_is_pcs_bypased, i));
}
}
+ if ((recovered_version <= 3) &&
+ (new_version >= 4)) {
+ remote_pause = 0;
+ for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
+ _SOC_IF_ERR_EXIT(
+ PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, remote_pause, i));
+ }
+ }
exit:
SOC_FUNC_RETURN;
@@ -1674,6 +1730,36 @@ int pm8x50_wb_buffer_init(int unit, int wb_buffer_index, pm_info_t pm_info)
_SOC_IF_ERR_EXIT(rv);
pm_info->wb_vars_ids[portIsPcsBypassed] = wb_var_id;
+ _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
+ SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_ber_war_enable",
+ wb_buffer_index, sizeof(uint32), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
+ _SOC_IF_ERR_EXIT(rv);
+ pm_info->wb_vars_ids[isBerWarEnable] = wb_var_id;
+
+ _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
+ SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ber_war_state",
+ wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
+ _SOC_IF_ERR_EXIT(rv);
+ pm_info->wb_vars_ids[berWarState] = wb_var_id;
+
+ _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
+ SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "ber_war_wait_count",
+ wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
+ _SOC_IF_ERR_EXIT(rv);
+ pm_info->wb_vars_ids[berWarWaitCount] = wb_var_id;
+
+ SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id,
+ "is_core_flexe_configured", wb_buffer_index, sizeof(int),
+ NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
+ _SOC_IF_ERR_EXIT(rv);
+ pm_info->wb_vars_ids[coreisFlexeConfigured] = wb_var_id;
+
+ _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
+ SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "an_400g_remote_pause",
+ wb_buffer_index, sizeof(int), NULL, MAX_PORTS_PER_PM8X50, VERSION(4));
+ _SOC_IF_ERR_EXIT(rv);
+ pm_info->wb_vars_ids[an400gRemotePause] = wb_var_id;
+
_SOC_IF_ERR_EXIT(soc_wb_engine_init_buffer(unit, SOC_WB_ENGINE_PORTMOD,
wb_buffer_index, FALSE));
@@ -2327,7 +2413,8 @@ int pm8x50_pm_init(int unit,
int i, rv;
int pm_is_active, ts_enable_port_count, is_initiator, pcs_reconfigured, active_lane_map;
int is_core_initialized, fec, invalid_port, rlm_state, fecType, txLaneMap, rxLaneMap, rlm_enabled;
- int an_state, is_400g_an, an_wait_link_count;
+ int an_state, is_400g_an, an_wait_link_count, is_ber_war_enable = 0, ber_war_state = 0, ber_war_wait_count = 0;
+ int core_is_flexe_configured, remote_pause;
uint8 ovco_pll_adv_lane_bitmap, tvco_pll_adv_lane_bitmap;
uint8 ovco_pll_active_lane_bitmap, tvco_pll_active_lane_bitmap;
int probe= 0;
@@ -2426,6 +2513,7 @@ int pm8x50_pm_init(int unit,
_SOC_IF_ERR_EXIT(PM8x50_RLM_ENABLE_GET(unit, pm_info, &rlm_enabled, i));
_SOC_IF_ERR_EXIT(PM8x50_RLM_STATE_GET(unit, pm_info, &rlm_state, i));
_SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, i));
+ _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_GET(unit, pm_info, &remote_pause, i));
/* need to re-register the call back */
if ( (port_local >= 0) && (((rlm_enabled) && (rlm_state >= PORTMOD_PORT_RLM_SEND_PACKET_DATA) &&
(rlm_state < PORTMOD_PORT_RLM_DONE)) ||
@@ -2556,6 +2644,28 @@ int pm8x50_pm_init(int unit,
an_wait_link_count = 0;
rv = PM8x50_400G_AN_WAIT_LINK_COUNT_SET(unit, pm_info, an_wait_link_count);
_SOC_IF_ERR_EXIT(rv);
+
+ is_ber_war_enable = 0;
+ ber_war_state = PM8X50_PORT_BER_WAR_STATE_COUNT;
+ ber_war_wait_count = 0;
+ for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
+ _SOC_IF_ERR_EXIT(PM8x50_BER_WAR_ENABLE_SET(unit, pm_info, is_ber_war_enable, i));
+
+ rv = PM8x50_BER_WAR_STATE_SET(unit, pm_info, ber_war_state, i);
+ _SOC_IF_ERR_EXIT(rv);
+
+ rv = PM8x50_BER_WAR_WAIT_COUNT_SET(unit, pm_info, ber_war_wait_count, i);
+ _SOC_IF_ERR_EXIT(rv);
+ }
+
+ core_is_flexe_configured = 0;
+ rv = PM8x50_IS_CORE_FLEXE_CONFIGURED_SET(unit, pm_info, core_is_flexe_configured);
+ _SOC_IF_ERR_EXIT(rv);
+
+ remote_pause = 0;
+ for (i = 0; i < MAX_PORTS_PER_PM8X50; i++) {
+ _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_SET(unit, pm_info, remote_pause, i));
+ }
}
exit:
@@ -5758,6 +5868,9 @@ int pm8x50_port_autoneg_ability_remote_get(int unit, int port, pm_info_t pm_info
int nof_phys, i;
phymod_autoneg_advert_ability_t autoneg_abilities[PM8x50_MAX_AN_ABILITY];
phymod_autoneg_advert_abilities_t an_advert_abilities;
+ int port_index, is_400g_an = 0, remote_pause = 0;
+ uint32 bitmap;
+ phymod_autoneg_status_t an_status;
SOC_INIT_FUNC_DEFS;
@@ -5772,6 +5885,21 @@ int pm8x50_port_autoneg_ability_remote_get(int unit, int port, pm_info_t pm_info
_SOC_IF_ERR_EXIT(phymod_phy_autoneg_remote_advert_ability_get(&phy_access, &an_advert_abilities));
+ /* next need to check 400G AN enabled or not */
+ _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
+ _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
+ _SOC_IF_ERR_EXIT(pm8x50_port_autoneg_status_get(unit, port, pm_info, &an_status));
+ if (is_400g_an && an_status.enabled && an_status.locked) {
+ _SOC_IF_ERR_EXIT(PM8x50_400G_AN_REMOTE_PAUSE_GET(unit, pm_info, &remote_pause, port_index));
+ an_advert_abilities.num_abilities = 1;
+ an_advert_abilities.autoneg_abilities[0].pause = remote_pause;
+ an_advert_abilities.autoneg_abilities[0].speed = 400000;
+ an_advert_abilities.autoneg_abilities[0].resolved_num_lanes = 8;
+ an_advert_abilities.autoneg_abilities[0].fec = phymod_fec_RS544_2XN;
+ an_advert_abilities.autoneg_abilities[0].channel = phymod_channel_long;
+ an_advert_abilities.autoneg_abilities[0].an_mode = phymod_AN_MODE_MSA;
+ }
+
if (an_advert_abilities.num_abilities > max_num_abilities) {
_SOC_EXIT_WITH_ERR(SOC_E_PARAM,
(_SOC_MSG("port %d: There are %d AN abilities. Larger array is needed."),
@@ -6138,7 +6266,7 @@ int pm8x50_port_phy_link_up_event(int unit, int port, pm_info_t pm_info)
int mac_stage_id, phy_acc;
uint32 reg_val;
uint32 timesync_enable, bitmap, flags = 0;
- int num_advert, num_remote;
+ int num_advert, num_remote, is_400g_an;
portmod_port_speed_ability_t advert_ability[PM8x50_MAX_AN_ABILITY];
portmod_port_speed_ability_t remote_ability[PM8x50_MAX_AN_ABILITY];
portmod_pause_control_t pause_ctrl;
@@ -6153,26 +6281,30 @@ int pm8x50_port_phy_link_up_event(int unit, int port, pm_info_t pm_info)
_SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap));
/* 1. Update for AN ports */
- _SOC_IF_ERR_EXIT(phymod_phy_autoneg_status_get(&phy_access, &an_status));
+ _SOC_IF_ERR_EXIT(pm8x50_port_autoneg_status_get(unit, port, pm_info, &an_status));
if ((an_status.enabled && an_status.locked)) {
+ /* read the 400G an enabled */
+ _SOC_IF_ERR_EXIT(PM8x50_400G_AN_ENABLE_GET(unit, pm_info, &is_400g_an, port_index));
/*!
* 1.1 Update port mode.
* For PM8x50 autoneg, once the port resolves and link up,
* cdmac_port_mode needs to be updated based on the PCS final port mode.
*/
- mac_stage_id = port_index / CDMAC_NUM_LANES;
- _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
+ if (!is_400g_an) {
+ mac_stage_id = port_index / CDMAC_NUM_LANES;
+ _SOC_IF_ERR_EXIT(_pm8x50_phy_access_get(unit, port, pm_info, &phy_acc));
- _SOC_IF_ERR_EXIT(READ_CDPORT_MODE_REGr(unit, phy_acc, ®_val));
+ _SOC_IF_ERR_EXIT(READ_CDPORT_MODE_REGr(unit, phy_acc, ®_val));
- if (mac_stage_id) {
- /* MAC1 is single-port mode */
- soc_reg_field_set(unit, CDPORT_MODE_REGr, ®_val, MAC1_PORT_MODEf, an_status.resolved_port_mode);
- } else {
- /* MAC0 is single-port mode */
- soc_reg_field_set(unit, CDPORT_MODE_REGr, ®_val, MAC0_PORT_MODEf, an_status.resolved_port_mode);
+ if (mac_stage_id) {
+ /* MAC1 is single-port mode */
+ soc_reg_field_set(unit, CDPORT_MODE_REGr, ®_val, MAC1_PORT_MODEf, an_status.resolved_port_mode);
+ } else {
+ /* MAC0 is single-port mode */
+ soc_reg_field_set(unit, CDPORT_MODE_REGr, ®_val, MAC0_PORT_MODEf, an_status.resolved_port_mode);
+ }
+ _SOC_IF_ERR_EXIT(WRITE_CDPORT_MODE_REGr(unit, phy_acc, reg_val));
}
- _SOC_IF_ERR_EXIT(WRITE_CDPORT_MODE_REGr(unit, phy_acc, reg_val));
/*!
* 1.2 Update pause settings.