From d60a2d3a106752747f352ea0e819f171f009c617 Mon Sep 17 00:00:00 2001 From: Xiao Wang Date: Sun, 25 Sep 2016 16:59:48 +0800 Subject: [PATCH] net/ixgbe/base: add flow control autoneg for X550em_a fiber This patch adds a separate function for enabling Flow Control (FC) auto-negotiation on X550em_a: - rename ixgbe_fc_autoneg_x550a() to ixgbe_fc_autoneg_backplane_x550em_a(). - create ixgbe_fc_autoneg_fiber_x550em_a() specifically for fiber. - add definitions for KRM_PCS_KX_AN_LP register and related bits. Signed-off-by: Xiao Wang Acked-by: Wenzhuo Lu --- drivers/net/ixgbe/base/ixgbe_type.h | 3 + drivers/net/ixgbe/base/ixgbe_x550.c | 85 ++++++++++++++++++++++++++++- drivers/net/ixgbe/base/ixgbe_x550.h | 3 +- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h index 1d38195cd5..f42ebafdb5 100644 --- a/drivers/net/ixgbe/base/ixgbe_type.h +++ b/drivers/net/ixgbe/base/ixgbe_type.h @@ -4143,6 +4143,7 @@ struct ixgbe_hw { #define IXGBE_KRM_AN_CNTL_4(P) ((P) ? 0x8238 : 0x4238) #define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248) #define IXGBE_KRM_PCS_KX_AN(P) ((P) ? 0x9918 : 0x5918) +#define IXGBE_KRM_PCS_KX_AN_LP(P) ((P) ? 0x991C : 0x591C) #define IXGBE_KRM_SGMII_CTRL(P) ((P) ? 0x82A0 : 0x42A0) #define IXGBE_KRM_LP_BASE_PAGE_HIGH(P) ((P) ? 0x836C : 0x436C) #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) @@ -4174,6 +4175,8 @@ struct ixgbe_hw { #define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE (1 << 29) #define IXGBE_KRM_PCS_KX_AN_SYM_PAUSE (1 << 1) #define IXGBE_KRM_PCS_KX_AN_ASM_PAUSE (1 << 2) +#define IXGBE_KRM_PCS_KX_AN_LP_SYM_PAUSE (1 << 2) +#define IXGBE_KRM_PCS_KX_AN_LP_ASM_PAUSE (1 << 3) #define IXGBE_KRM_AN_CNTL_4_ECSR_AN37_OVER_73 (1 << 29) #define IXGBE_KRM_AN_CNTL_8_LINEAR (1 << 0) #define IXGBE_KRM_AN_CNTL_8_LIMITING (1 << 1) diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c index b0697aaf60..bf3da103ef 100644 --- a/drivers/net/ixgbe/base/ixgbe_x550.c +++ b/drivers/net/ixgbe/base/ixgbe_x550.c @@ -656,13 +656,14 @@ s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw) mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a; mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a; - mac->ops.fc_autoneg = ixgbe_fc_autoneg_x550a; switch (mac->ops.get_media_type(hw)) { case ixgbe_media_type_fiber: mac->ops.setup_fc = ixgbe_setup_fc_fiber_x550em_a; + mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; break; case ixgbe_media_type_backplane: + mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; break; default: @@ -3958,12 +3959,12 @@ out: } /** - * ixgbe_fc_autoneg_x550a - Enable flow control IEEE clause 37 + * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 * @hw: pointer to hardware structure * * Enable flow control according to IEEE clause 37. **/ -void ixgbe_fc_autoneg_x550a(struct ixgbe_hw *hw) +void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) { u32 link_s1, lp_an_page_low, an_cntl_1; s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; @@ -3995,6 +3996,7 @@ void ixgbe_fc_autoneg_x550a(struct ixgbe_hw *hw) if (status != IXGBE_SUCCESS || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { DEBUGOUT("Auto-Negotiation did not complete\n"); + status = IXGBE_ERR_FC_NOT_NEGOTIATED; goto out; } @@ -4034,6 +4036,83 @@ out: } } +/** + * ixgbe_fc_autoneg_fiber_x550em_a - Enable flow control IEEE clause 37 + * @hw: pointer to hardware structure + * + * Enable flow control according to IEEE clause 37. + **/ +void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) +{ + u32 link_s1, pcs_an_lp, pcs_an; + s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; + ixgbe_link_speed speed; + bool link_up; + + /* AN should have completed when the cable was plugged in. + * Look for reasons to bail out. Bail out if: + * - FC autoneg is disabled, or if + * - link is not up. + */ + if (hw->fc.disable_fc_autoneg) { + ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, + "Flow control autoneg is disabled"); + goto out; + } + + hw->mac.ops.check_link(hw, &speed, &link_up, false); + if (!link_up) { + ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); + goto out; + } + + /* Check if auto-negotiation has completed */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_S1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); + + if (status != IXGBE_SUCCESS || + (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { + DEBUGOUT("Auto-Negotiation did not complete\n"); + status = IXGBE_ERR_FC_NOT_NEGOTIATED; + goto out; + } + + /* Determine advertised flow control */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &pcs_an); + + if (status != IXGBE_SUCCESS) { + DEBUGOUT("Auto-Negotiation did not complete\n"); + goto out; + } + + /* Determine link parter flow control */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PCS_KX_AN_LP(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &pcs_an_lp); + + if (status != IXGBE_SUCCESS) { + DEBUGOUT("Auto-Negotiation did not complete\n"); + goto out; + } + + status = ixgbe_negotiate_fc(hw, pcs_an, pcs_an_lp, + IXGBE_KRM_PCS_KX_AN_SYM_PAUSE, + IXGBE_KRM_PCS_KX_AN_ASM_PAUSE, + IXGBE_KRM_PCS_KX_AN_LP_SYM_PAUSE, + IXGBE_KRM_PCS_KX_AN_LP_ASM_PAUSE); + +out: + if (status == IXGBE_SUCCESS) { + hw->fc.fc_was_autonegged = true; + } else { + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; + } +} + /** * ixgbe_setup_fc_backplane_x550em_a - Set up flow control * @hw: pointer to hardware structure diff --git a/drivers/net/ixgbe/base/ixgbe_x550.h b/drivers/net/ixgbe/base/ixgbe_x550.h index d8278fa5cd..db27c8419d 100644 --- a/drivers/net/ixgbe/base/ixgbe_x550.h +++ b/drivers/net/ixgbe/base/ixgbe_x550.h @@ -109,7 +109,8 @@ s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); s32 ixgbe_setup_fc_fiber_x550em_a(struct ixgbe_hw *hw); s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw); -void ixgbe_fc_autoneg_x550a(struct ixgbe_hw *hw); +void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw); +void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw); s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, -- 2.20.1