From patchwork Sat Aug 27 15:48:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiao Wang X-Patchwork-Id: 15486 X-Patchwork-Delegate: bruce.richardson@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id F2EA45A9E; Sat, 27 Aug 2016 17:49:27 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 4B30A5A7B for ; Sat, 27 Aug 2016 17:49:21 +0200 (CEST) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga103.fm.intel.com with ESMTP; 27 Aug 2016 08:49:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,587,1464678000"; d="scan'208";a="1859804" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga004.jf.intel.com with ESMTP; 27 Aug 2016 08:49:19 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id u7RFnH7u008813; Sat, 27 Aug 2016 23:49:17 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id u7RFnEC3017145; Sat, 27 Aug 2016 23:49:16 +0800 Received: (from xiaowan1@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id u7RFnESc017141; Sat, 27 Aug 2016 23:49:14 +0800 From: Xiao Wang To: wenzhuo.lu@intel.com Cc: dev@dpdk.org, Xiao Wang Date: Sat, 27 Aug 2016 23:48:04 +0800 Message-Id: <1472312902-16963-22-git-send-email-xiao.w.wang@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1472312902-16963-1-git-send-email-xiao.w.wang@intel.com> References: <1472312902-16963-1-git-send-email-xiao.w.wang@intel.com> Subject: [dpdk-dev] [PATCH 21/39] net/ixgbe/base: support X550em_a SGMII FC autoneg X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Create FC (flow control) setup and enable FC function with code to configure the PHY registers to advertize FC settings according to the user requested settings and to negotiate the same with the link partner and arrive at a negotiated setting (RX and TX enabled, TX only enabled, FC disabled and RX enabled (which also enables TX) ). Remove the part of code that performs FC auto-negotiation (AN) in ixgbe_setup_m88 and put it in a new function to maintain consistency with other FC AN implementations so far. Add function pointers to the setup-fc and enable-fc functions so that they get called during init to perform FC AN. Signed-off-by: Xiao Wang --- drivers/net/ixgbe/base/ixgbe_x550.c | 172 ++++++++++++++++++++++++++++++++---- drivers/net/ixgbe/base/ixgbe_x550.h | 2 + 2 files changed, 158 insertions(+), 16 deletions(-) diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c index c8873ee..a9f4d2a 100644 --- a/drivers/net/ixgbe/base/ixgbe_x550.c +++ b/drivers/net/ixgbe/base/ixgbe_x550.c @@ -676,6 +676,12 @@ s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw) break; } + if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || + (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { + mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; + mac->ops.setup_fc = ixgbe_setup_fc_sgmii_x550em_a; + } + return ret_val; } @@ -2182,27 +2188,15 @@ STATIC s32 ixgbe_setup_m88(struct ixgbe_hw *hw) rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_AN, 0, ®); if (rc) goto out; - reg &= ~IXGBE_M88E1500_COPPER_AN_AS_PAUSE; - reg &= ~IXGBE_M88E1500_COPPER_AN_PAUSE; reg &= ~IXGBE_M88E1500_COPPER_AN_T4; reg &= ~IXGBE_M88E1500_COPPER_AN_100TX_FD; reg &= ~IXGBE_M88E1500_COPPER_AN_100TX_HD; reg &= ~IXGBE_M88E1500_COPPER_AN_10TX_FD; reg &= ~IXGBE_M88E1500_COPPER_AN_10TX_HD; - switch (hw->fc.current_mode) { - case ixgbe_fc_full: - reg |= IXGBE_M88E1500_COPPER_AN_PAUSE; - break; - case ixgbe_fc_rx_pause: - reg |= IXGBE_M88E1500_COPPER_AN_PAUSE; - reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; - break; - case ixgbe_fc_tx_pause: - reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; - break; - default: - break; - } + + /* Flow control auto negotiation configuration was moved from here to + * the function ixgbe_setup_fc_sgmii_x550em_a() + */ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) reg |= IXGBE_M88E1500_COPPER_AN_100TX_FD; @@ -4122,6 +4116,152 @@ out: } /** + * ixgbe_fc_autoneg_sgmii_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_sgmii_x550em_a(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; + u16 reg, pcs_an_lp, pcs_an; + 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->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_STATUS, + IXGBE_MDIO_ZERO_DEV_TYPE, ®); + if (status != IXGBE_SUCCESS || + (reg & IXGBE_M88E1500_COPPER_STATUS_AN_DONE) == 0) { + DEBUGOUT("Auto-Negotiation did not complete\n"); + status = IXGBE_ERR_FC_NOT_NEGOTIATED; + goto out; + } + + /* Get the advertized flow control */ + status = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_AN, + IXGBE_MDIO_ZERO_DEV_TYPE, &pcs_an); + if (status != IXGBE_SUCCESS) + goto out; + + /* Get link partner's flow control */ + status = hw->phy.ops.read_reg(hw, + IXGBE_M88E1500_COPPER_AN_LP_ABILITY, + IXGBE_MDIO_ZERO_DEV_TYPE, &pcs_an_lp); + if (status != IXGBE_SUCCESS) + goto out; + + /* Negotiate the flow control */ + status = ixgbe_negotiate_fc(hw, (u32)pcs_an, (u32)pcs_an_lp, + IXGBE_M88E1500_COPPER_AN_PAUSE, + IXGBE_M88E1500_COPPER_AN_AS_PAUSE, + IXGBE_M88E1500_COPPER_AN_LP_PAUSE, + IXGBE_M88E1500_COPPER_AN_LP_AS_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_sgmii_x550em_a - Set up flow control + * @hw: pointer to hardware structure + * + * Called at init time to set up flow control. + **/ +s32 ixgbe_setup_fc_sgmii_x550em_a(struct ixgbe_hw *hw) +{ + u16 reg; + s32 rc; + + /* Validate the requested mode */ + if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { + ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, + "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); + return IXGBE_ERR_INVALID_LINK_SETTINGS; + } + + if (hw->fc.requested_mode == ixgbe_fc_default) + hw->fc.requested_mode = ixgbe_fc_full; + + /* Read contents of the Auto-Negotiation register, page 0 reg 4 */ + rc = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_AN, + IXGBE_MDIO_ZERO_DEV_TYPE, ®); + if (rc) + goto out; + + /* Disable all the settings related to Flow control Auto-negotiation */ + reg &= ~IXGBE_M88E1500_COPPER_AN_AS_PAUSE; + reg &= ~IXGBE_M88E1500_COPPER_AN_PAUSE; + + /* Configure the Asymmetric and symmetric pause according to the user + * requested mode. + */ + switch (hw->fc.requested_mode) { + case ixgbe_fc_full: + reg |= IXGBE_M88E1500_COPPER_AN_PAUSE; + reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; + break; + case ixgbe_fc_rx_pause: + reg |= IXGBE_M88E1500_COPPER_AN_PAUSE; + reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; + break; + case ixgbe_fc_tx_pause: + reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; + break; + default: + break; + } + + /* Write back to the Auto-Negotiation register with newly configured + * fields + */ + hw->phy.ops.write_reg(hw, IXGBE_M88E1500_COPPER_AN, + IXGBE_MDIO_ZERO_DEV_TYPE, reg); + + /* In this section of the code we restart Auto-negotiation */ + + /* Read the CONTROL register, Page 0 reg 0 */ + rc = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_CTRL, + IXGBE_MDIO_ZERO_DEV_TYPE, ®); + if (rc) + goto out; + + /* Set the bit to restart Auto-Neg. The bit to enable Auto-neg is ON + * by default + */ + reg |= IXGBE_M88E1500_COPPER_CTRL_RESTART_AN; + + /* write the new values to the register to restart Auto-Negotiation */ + hw->phy.ops.write_reg(hw, IXGBE_M88E1500_COPPER_CTRL, + IXGBE_MDIO_ZERO_DEV_TYPE, reg); + +out: + return rc; +} + +/** * 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 db27c84..c7253f0 100644 --- a/drivers/net/ixgbe/base/ixgbe_x550.h +++ b/drivers/net/ixgbe/base/ixgbe_x550.h @@ -109,8 +109,10 @@ 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); +s32 ixgbe_setup_fc_sgmii_x550em_a(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); +void ixgbe_fc_autoneg_sgmii_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,