openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

commit 0f43eb2be0f63b7b0d3952e61cac0096af83f808
parent b0dfbe8efbf25730cc29dc05c073502120465836
Author: Broadcom SDK Release <sdk.releases@broadcom.com>
Date:   Mon, 13 Jan 2020 15:28:21 -0800

SDK-173659: SDK-173659 Configure pause settings after AN is resolved on PM8x50

Devices: 56980_A0,56980_B0
Module: PortMod

Diffstat:
Msdk-6.5.16/src/bcm/esw/portctrl.c | 83++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msdk-6.5.16/src/soc/portmod/pms/pm8x50.c | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 114 insertions(+), 40 deletions(-)

diff --git a/sdk-6.5.16/src/bcm/esw/portctrl.c b/sdk-6.5.16/src/bcm/esw/portctrl.c @@ -2535,46 +2535,55 @@ bcmi_esw_portctrl_update(int unit, bcm_gport_t port, int link) * MACs accordingly. Link can also be achieved thru parallel detect. * In this case, it should be treated as in the forced mode. */ - if (an_status.enabled && an_status.locked) { - bcm_port_ability_t local_advert, remote_advert; - int tx_pause, rx_pause; - portmod_pause_control_t pause_control; +#ifdef PORTMOD_PM8X50_SUPPORT + if (pm_type == portmodDispatchTypePm8x50) { + /* Do nothing for PM8x50. Pause settings for AN will be taken care + * inside Portmod. + */ + } else +#endif + { + if (an_status.enabled && an_status.locked) { + bcm_port_ability_t local_advert, remote_advert; + int tx_pause, rx_pause; + portmod_pause_control_t pause_control; - BCM_IF_ERROR_RETURN - (bcmi_esw_portctrl_ability_advert_get(unit, port, - &local_advert, NULL)); - BCM_IF_ERROR_RETURN - (bcmi_esw_portctrl_ability_remote_get(unit, port, - &remote_advert, NULL)); + BCM_IF_ERROR_RETURN + (bcmi_esw_portctrl_ability_advert_get(unit, port, + &local_advert, NULL)); + BCM_IF_ERROR_RETURN + (bcmi_esw_portctrl_ability_remote_get(unit, port, + &remote_advert, NULL)); - /* - * IEEE 802.3 Flow Control Resolution. - * Please see $SDK/doc/pause-resolution.txt for more information. - */ - if (duplex) { - tx_pause = - ((remote_advert.pause & SOC_PA_PAUSE_RX) && - (local_advert.pause & SOC_PA_PAUSE_RX)) || - ((remote_advert.pause & SOC_PA_PAUSE_RX) && - !(remote_advert.pause & SOC_PA_PAUSE_TX) && - (local_advert.pause & SOC_PA_PAUSE_TX)); - - rx_pause = - ((remote_advert.pause & SOC_PA_PAUSE_RX) && - (local_advert.pause & SOC_PA_PAUSE_RX)) || - ((local_advert.pause & SOC_PA_PAUSE_RX) && - (remote_advert.pause & SOC_PA_PAUSE_TX) && - !(local_advert.pause & SOC_PA_PAUSE_TX)); - } else { - rx_pause = tx_pause = 0; - } + /* + * IEEE 802.3 Flow Control Resolution. + * Please see $SDK/doc/pause-resolution.txt for more information. + */ + if (duplex) { + tx_pause = + ((remote_advert.pause & SOC_PA_PAUSE_RX) && + (local_advert.pause & SOC_PA_PAUSE_RX)) || + ((remote_advert.pause & SOC_PA_PAUSE_RX) && + !(remote_advert.pause & SOC_PA_PAUSE_TX) && + (local_advert.pause & SOC_PA_PAUSE_TX)); + + rx_pause = + ((remote_advert.pause & SOC_PA_PAUSE_RX) && + (local_advert.pause & SOC_PA_PAUSE_RX)) || + ((local_advert.pause & SOC_PA_PAUSE_RX) && + (remote_advert.pause & SOC_PA_PAUSE_TX) && + !(local_advert.pause & SOC_PA_PAUSE_TX)); + } else { + rx_pause = tx_pause = 0; + } - PORTMOD_IF_ERROR_RETURN - (portmod_port_pause_control_get(unit, pport, &pause_control)); - pause_control.rx_enable = rx_pause; - pause_control.tx_enable = tx_pause; - PORTMOD_IF_ERROR_RETURN - (portmod_port_pause_control_set(unit, pport, &pause_control)); + PORTMOD_IF_ERROR_RETURN + (portmod_port_pause_control_get(unit, pport, &pause_control)); + pause_control.rx_enable = rx_pause; + pause_control.tx_enable = tx_pause; + PORTMOD_IF_ERROR_RETURN + (portmod_port_pause_control_set(unit, pport, &pause_control)); + } } /* Enable the MAC */ diff --git a/sdk-6.5.16/src/soc/portmod/pms/pm8x50.c b/sdk-6.5.16/src/soc/portmod/pms/pm8x50.c @@ -6126,6 +6126,7 @@ exit: } /* link up event */ /* 1. AN ports: Update port mode based on reslved speed mode. + * Program resolved Pause settings. * 2. 1588 ports: timesync adjust. */ int pm8x50_port_phy_link_up_event(int unit, int port, pm_info_t pm_info) @@ -6137,6 +6138,12 @@ 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; + 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; + portmod_port_phy_pause_t pause_local, pause_remote; + uint8 rx_pause, tx_pause; SOC_INIT_FUNC_DEFS; @@ -6145,11 +6152,14 @@ int pm8x50_port_phy_link_up_event(int unit, int port, pm_info_t pm_info) &params, 1, &phy_access, &nof_phys, NULL)); _SOC_IF_ERR_EXIT(_pm8x50_port_index_get(unit, port, pm_info, &port_index, &bitmap)); - /* 1. Update Port_mode for AN ports */ + /* 1. Update for AN ports */ _SOC_IF_ERR_EXIT(phymod_phy_autoneg_status_get(&phy_access, &an_status)); - /* for the PM8x50 autoneg, once the port resolves and link up and - cdmac_port_mode needs to be updated based on the pcs final port mode */ if ((an_status.enabled && an_status.locked)) { + /*! + * 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)); @@ -6163,6 +6173,61 @@ int pm8x50_port_phy_link_up_event(int unit, int port, pm_info_t pm_info) soc_reg_field_set(unit, CDPORT_MODE_REGr, &reg_val, MAC0_PORT_MODEf, an_status.resolved_port_mode); } _SOC_IF_ERR_EXIT(WRITE_CDPORT_MODE_REGr(unit, phy_acc, reg_val)); + + /*! + * 1.2 Update pause settings. + * Please see $SDK/doc/pause-resolution.txt for more information. + */ + _SOC_IF_ERR_EXIT + (pm8x50_port_autoneg_ability_advert_get(unit, port, pm_info, + PM8x50_MAX_AN_ABILITY, + advert_ability, &num_advert)); + _SOC_IF_ERR_EXIT + (pm8x50_port_autoneg_ability_remote_get(unit, port, pm_info, + PM8x50_MAX_AN_ABILITY, + remote_ability, &num_remote)); + + if (num_advert && num_remote) { + pause_local = advert_ability[0].pause; + pause_remote = remote_ability[0].pause; + if ( + ((pause_local == PORTMOD_PORT_PHY_PAUSE_RX) && + (pause_remote == PORTMOD_PORT_PHY_PAUSE_TX)) || + ((pause_local == PORTMOD_PORT_PHY_PAUSE_RX || + pause_local == PORTMOD_PORT_PHY_PAUSE_SYMM) && + (pause_remote == PORTMOD_PORT_PHY_PAUSE_RX || + pause_remote == PORTMOD_PORT_PHY_PAUSE_SYMM)) + ) { + rx_pause = 1; + } else { + rx_pause = 0; + } + if ( + ((pause_local == PORTMOD_PORT_PHY_PAUSE_RX || + pause_local == PORTMOD_PORT_PHY_PAUSE_SYMM) && + (pause_remote == PORTMOD_PORT_PHY_PAUSE_RX || + pause_remote == PORTMOD_PORT_PHY_PAUSE_SYMM)) || + ((pause_local == PORTMOD_PORT_PHY_PAUSE_TX) && + (pause_remote == PORTMOD_PORT_PHY_PAUSE_RX)) + ) { + tx_pause = 1; + } else { + tx_pause = 0; + } + } else { + tx_pause = 0; + rx_pause = 0; + } + + _SOC_IF_ERR_EXIT + (pm8x50_port_pause_control_get(unit, port, pm_info, &pause_ctrl)); + if ((pause_ctrl.rx_enable != rx_pause) || + (pause_ctrl.tx_enable != tx_pause)) { + pause_ctrl.rx_enable = rx_pause; + pause_ctrl.tx_enable = tx_pause; + _SOC_IF_ERR_EXIT + (pm8x50_port_pause_control_set(unit, port, pm_info, &pause_ctrl)); + } }