From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 338464404F; Wed, 12 Jun 2024 17:27:29 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 23DD74333E; Wed, 12 Jun 2024 17:07:26 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.10]) by mails.dpdk.org (Postfix) with ESMTP id 241CB42ED5 for ; Wed, 12 Jun 2024 17:07:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1718204835; x=1749740835; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=44xRWGOY4UbGvhPdkLWf3CyC9+aeOx56RtbTSjrWOBQ=; b=JKVZdg1nZWfWMK6UTx8rTvaBs/cnS6O1xJVegnxjfTAI5nxoQTY5N78o Y/wxonMHEIi66lnm4ohK0CllCp0j8tmN5uS1t9f48q6CcT7yWpxRducB4 hOO5FLfSEGk/O8nwRYDnrsiMJtzcxa6llsNeltDq8GtV3VdBW+rgqYyS/ zTwNUtPL45GI/753YBWwaw6lvxqiMN1TViEaA7LN4ldDgtHRjDYb7gO2Z srFnOPojG8pDau8w7SNB9qawwK9bh6KHH/nQzEK62+3I4+LFKfRH+Q6ig sLjdd/J5k3uxfAQbJxM5l2EbgpzyGW9rkjWgwk0QUE9tBEw17xOt0DpiB g==; X-CSE-ConnectionGUID: +DX+lPowR4qMADti2oZqBQ== X-CSE-MsgGUID: qRNP+wTbQxS69Kc4teczcw== X-IronPort-AV: E=McAfee;i="6700,10204,11101"; a="32460173" X-IronPort-AV: E=Sophos;i="6.08,233,1712646000"; d="scan'208";a="32460173" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2024 08:07:15 -0700 X-CSE-ConnectionGUID: vXWV60RMTrKJ1B2jgoeYlg== X-CSE-MsgGUID: KSMj0c/HRIWqkkDnvHH8mA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,233,1712646000"; d="scan'208";a="39926085" Received: from silpixa00401119.ir.intel.com ([10.55.129.167]) by orviesa009.jf.intel.com with ESMTP; 12 Jun 2024 08:07:13 -0700 From: Anatoly Burakov To: dev@dpdk.org Cc: Ian Stokes , bruce.richardson@intel.com, Sergey Temerkhanov , Milena Olech , Siddaraju DH Subject: [PATCH v2 142/148] net/ice/base: rework multiple functions Date: Wed, 12 Jun 2024 16:02:16 +0100 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: <20240430154014.1026-1-ian.stokes@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Ian Stokes Multpiple functions that have been implemented, rework and removed are contained in this patch. Specifaclly the patch combines the following commits: - Implement TX interrupt enablement functions. Introduce functions enabling/disabling TX TS interrupts for the E822 and ETH56G PHYs - Remove bypass modeRemove bypass mode. Previous implementation switches between bypass and Vernier mode dynamically. However bypass mode should be removed due to low precision. - Make Tx and Rx vernier offset calibration independent. The Tx and Rx calibration and timestamp generation blocks are independent. It is not required to wait for both to complete before programming the offsets. Instead, we can program the offset for each independently as soon as they are ready. Remove the ice_phy_calc_vernier_e822 function. Modify the ice_phy_cfg_tx_offset_e822 and ice_phy_cfg_rx_offset_e822 functions with the following additions: a) Check the relevant P_REG_*_OR bit first and do nothing if the offset has already been programmed b) Check the P_REG_*_OV_STATUS bit to determine if the offset status is ready, meaning that the hardware vernier calibration steps have completed. Return ICE_ERR_NOT_READY if the offset is not yet read. The driver can now simply call ice_phy_cfg_rx_offset_e822 and ice_phy_cfg_tx_offset_e822 periodically until the offsets have been programmed. In this way, the Tx and Rx blocks will be enabled independently without each waiting on the other block to complete. This can enable faster calibration on some setups which have a low rate of either Tx or Rx traffic. Signed-off-by: Sergey Temerkhanov Signed-off-by: Milena Olech Signed-off-by: Siddaraju DH Signed-off-by: Ian Stokes --- drivers/net/ice/base/ice_ptp_hw.c | 282 +++++++++++------------------- drivers/net/ice/base/ice_ptp_hw.h | 10 +- drivers/net/ice/ice_ethdev.c | 2 +- 3 files changed, 112 insertions(+), 182 deletions(-) diff --git a/drivers/net/ice/base/ice_ptp_hw.c b/drivers/net/ice/base/ice_ptp_hw.c index b351784f4a..f7d397ae51 100644 --- a/drivers/net/ice/base/ice_ptp_hw.c +++ b/drivers/net/ice/base/ice_ptp_hw.c @@ -2040,6 +2040,41 @@ int ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port) return ice_write_phy_reg_eth56g(hw, port, PHY_REG_RX_OFFSET_READY, 1); } +/** + * ice_phy_cfg_intr_eth56g - Configure TX timestamp interrupt + * @hw: pointer to the HW struct + * @port: the timestamp port + * @ena: enable or disable interrupt + * @threshold: interrupt threshold + * + * Configure TX timestamp interrupt for the specified port + */ + +int +ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold) +{ + int err; + u32 val; + + err = ice_read_phy_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, + &val); + if (err) + return err; + + if (ena) { + val |= PHY_TS_INT_CONFIG_ENA_M; + val &= ~PHY_TS_INT_CONFIG_THRESHOLD_M; + val |= ((threshold << PHY_TS_INT_CONFIG_THRESHOLD_S) & + PHY_TS_INT_CONFIG_THRESHOLD_M); + } else { + val &= ~PHY_TS_INT_CONFIG_ENA_M; + } + + err = ice_write_phy_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, + val); + return err; +} + /** * ice_ptp_clear_phy_offset_ready_eth56g - Clear PHY OFFSET_READY registers * @hw: pointer to the HW struct @@ -2228,7 +2263,6 @@ ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset) * ice_start_phy_timer_eth56g - Start the PHY clock timer * @hw: pointer to the HW struct * @port: the PHY port to start - * @bypass: unused, for compatibility * * Start the clock of a PHY port. This must be done as part of the flow to * re-calibrate Tx and Rx timestamping offsets whenever the clock time is @@ -2236,7 +2270,7 @@ ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset) * */ int -ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool bypass) +ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port) { int err; u32 lo, hi; @@ -3837,6 +3871,28 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) enum ice_ptp_fec_mode fec_mode; u64 total_offset, val; int err; + u32 reg; + + /* Nothing to do if we've already programmed the offset */ + err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OR, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OR for port %u, err %d\n", + port, err); + return err; + } + + if (reg) + return 0; + + err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, err %d\n", + port, err); + return err; + } + + if (!(reg & P_REG_TX_OV_STATUS_OV_M)) + return ICE_ERR_NOT_READY; err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); if (err) @@ -3894,47 +3950,6 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) return 0; } -/** - * ice_phy_cfg_fixed_tx_offset_e822 - Configure Tx offset for bypass mode - * @hw: pointer to the HW struct - * @port: the PHY port to configure - * - * Calculate and program the fixed Tx offset, and indicate that the offset is - * ready. This can be used when operating in bypass mode. - */ -static int -ice_phy_cfg_fixed_tx_offset_e822(struct ice_hw *hw, u8 port) -{ - enum ice_ptp_link_spd link_spd; - enum ice_ptp_fec_mode fec_mode; - int err; - u64 total_offset; - - err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); - if (err) - return err; - - total_offset = ice_calc_fixed_tx_offset_e822(hw, link_spd); - - /* Program the fixed Tx offset into the P_REG_TOTAL_TX_OFFSET_L - * register, then indicate that the Tx offset is ready. After this, - * timestamps will be enabled. - * - * Note that this skips including the more precise offsets generated - * by the Vernier calibration. - */ - err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_TX_OFFSET_L, - total_offset); - if (err) - return err; - - err = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 1); - if (err) - return err; - - return 0; -} - /** * ice_phy_calc_pmd_adj_e822 - Calculate PMD adjustment for Rx * @hw: pointer to the HW struct @@ -4157,6 +4172,28 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) enum ice_ptp_fec_mode fec_mode; u64 total_offset, pmd, val; int err; + u32 reg; + + /* Nothing to do if we've already programmed the offset */ + err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OR, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OR for port %u, err %d\n", + port, err); + return err; + } + + if (reg) + return 0; + + err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, err %d\n", + port, err); + return err; + } + + if (!(reg & P_REG_RX_OV_STATUS_OV_M)) + return ICE_ERR_NOT_READY; err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); if (err) @@ -4253,47 +4290,6 @@ static int ice_ptp_clear_phy_offset_ready_e822(struct ice_hw *hw) return 0; } -/** - * ice_phy_cfg_fixed_rx_offset_e822 - Configure fixed Rx offset for bypass mode - * @hw: pointer to the HW struct - * @port: the PHY port to configure - * - * Calculate and program the fixed Rx offset, and indicate that the offset is - * ready. This can be used when operating in bypass mode. - */ -static int -ice_phy_cfg_fixed_rx_offset_e822(struct ice_hw *hw, u8 port) -{ - enum ice_ptp_link_spd link_spd; - enum ice_ptp_fec_mode fec_mode; - int err; - u64 total_offset; - - err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); - if (err) - return err; - - total_offset = ice_calc_fixed_rx_offset_e822(hw, link_spd); - - /* Program the fixed Rx offset into the P_REG_TOTAL_RX_OFFSET_L - * register, then indicate that the Rx offset is ready. After this, - * timestamps will be enabled. - * - * Note that this skips including the more precise offsets generated - * by Vernier calibration. - */ - err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_RX_OFFSET_L, - total_offset); - if (err) - return err; - - err = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 1); - if (err) - return err; - - return 0; -} - /** * ice_read_phy_and_phc_time_e822 - Simultaneously capture PHC and PHY time * @hw: pointer to the HW struct @@ -4474,19 +4470,14 @@ ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) * ice_start_phy_timer_e822 - Start the PHY clock timer * @hw: pointer to the HW struct * @port: the PHY port to start - * @bypass: if true, start the PHY in bypass mode * * Start the clock of a PHY port. This must be done as part of the flow to * re-calibrate Tx and Rx timestamping offsets whenever the clock time is * initialized or when link speed changes. * - * Bypass mode enables timestamps immediately without waiting for Vernier - * calibration to complete. Hardware will still continue taking Vernier - * measurements on Tx or Rx of packets, but they will not be applied to - * timestamps. Use ice_phy_exit_bypass_e822 to exit bypass mode once hardware - * has completed offset calculation. + * Hardware will take Vernier measurements on Tx or Rx of packets. */ -int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass) +int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) { u32 lo, hi, val; u64 incval; @@ -4567,23 +4558,6 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass) if (err) return err; - if (bypass) { - val |= P_REG_PS_BYPASS_MODE_M; - /* Enter BYPASS mode, enabling timestamps immediately. */ - err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); - if (err) - return err; - - /* Program the fixed Tx offset */ - err = ice_phy_cfg_fixed_tx_offset_e822(hw, port); - if (err) - return err; - - /* Program the fixed Rx offset */ - err = ice_phy_cfg_fixed_rx_offset_e822(hw, port); - if (err) - return err; - } ice_debug(hw, ICE_DBG_PTP, "Enabled clock on PHY port %u\n", port); @@ -4626,87 +4600,41 @@ ice_get_phy_tx_tstamp_ready_e822(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) } /** - * ice_phy_exit_bypass_e822 - Exit bypass mode, after vernier calculations + * ice_phy_cfg_intr_e822 - Configure TX timestamp interrupt * @hw: pointer to the HW struct - * @port: the PHY port to configure + * @quad: the timestamp quad + * @ena: enable or disable interrupt + * @threshold: interrupt threshold * - * After hardware finishes vernier calculations for the Tx and Rx offset, this - * function can be used to exit bypass mode by updating the total Tx and Rx - * offsets, and then disabling bypass. This will enable hardware to include - * the more precise offset calibrations, increasing precision of the generated - * timestamps. - * - * This cannot be done until hardware has measured the offsets, which requires - * waiting until at least one packet has been sent and received by the device. + * Configure TX timestamp interrupt for the specified quad */ -int ice_phy_exit_bypass_e822(struct ice_hw *hw, u8 port) + +int +ice_phy_cfg_intr_e822(struct ice_hw *hw, u8 quad, bool ena, u8 threshold) { int err; u32 val; - err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, &val); - if (err) { - ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, err %d\n", - port, err); + err = ice_read_quad_reg_e822(hw, quad, + Q_REG_TX_MEM_GBL_CFG, + &val); + if (err) return err; - } - - if (!(val & P_REG_TX_OV_STATUS_OV_M)) { - ice_debug(hw, ICE_DBG_PTP, "Tx offset is not yet valid for port %u\n", - port); - return ICE_ERR_NOT_READY; - } - - err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, &val); - if (err) { - ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, err %d\n", - port, err); - return err; - } - - if (!(val & P_REG_TX_OV_STATUS_OV_M)) { - ice_debug(hw, ICE_DBG_PTP, "Rx offset is not yet valid for port %u\n", - port); - return ICE_ERR_NOT_READY; - } - err = ice_phy_cfg_tx_offset_e822(hw, port); - if (err) { - ice_debug(hw, ICE_DBG_PTP, "Failed to program total Tx offset for port %u, err %d\n", - port, err); - return err; - } - - err = ice_phy_cfg_rx_offset_e822(hw, port); - if (err) { - ice_debug(hw, ICE_DBG_PTP, "Failed to program total Rx offset for port %u, err %d\n", - port, err); - return err; - } - - /* Exit bypass mode now that the offset has been updated */ - err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); - if (err) { - ice_debug(hw, ICE_DBG_PTP, "Failed to read P_REG_PS for port %u, err %d\n", - port, err); - return err; - } - - if (!(val & P_REG_PS_BYPASS_MODE_M)) - ice_debug(hw, ICE_DBG_PTP, "Port %u not in bypass mode\n", - port); - - val &= ~P_REG_PS_BYPASS_MODE_M; - err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); - if (err) { - ice_debug(hw, ICE_DBG_PTP, "Failed to disable bypass for port %u, err %d\n", - port, err); - return err; + if (ena) { + val |= Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M; + val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_THR_M; + val |= ((threshold << Q_REG_TX_MEM_GBL_CFG_INTR_THR_S) & + Q_REG_TX_MEM_GBL_CFG_INTR_THR_M); + } else { + val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M; } - ice_info(hw, "Exiting bypass mode on PHY port %u\n", port); + err = ice_write_quad_reg_e822(hw, quad, + Q_REG_TX_MEM_GBL_CFG, + val); - return 0; + return err; } /* E810 functions diff --git a/drivers/net/ice/base/ice_ptp_hw.h b/drivers/net/ice/base/ice_ptp_hw.h index 90db99327c..345d343a5a 100644 --- a/drivers/net/ice/base/ice_ptp_hw.h +++ b/drivers/net/ice/base/ice_ptp_hw.h @@ -256,11 +256,11 @@ ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port); int ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset); -int -ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass); +int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port); int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port); int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port); -int ice_phy_exit_bypass_e822(struct ice_hw *hw, u8 port); +int +ice_phy_cfg_intr_e822(struct ice_hw *hw, u8 quad, bool ena, u8 threshold); /* E810 family functions */ int ice_ptp_init_phy_e810(struct ice_hw *hw); @@ -301,9 +301,11 @@ ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status); int ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset); int -ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool bypass); +ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port); int ice_phy_cfg_tx_offset_eth56g(struct ice_hw *hw, u8 port); int ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port); +int +ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold); #define ICE_ETH56G_PLL_FREQ 800000000 #define ICE_ETH56G_NOMINAL_INCVAL 0x140000000ULL diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c index f4394487a8..5c1d83e605 100644 --- a/drivers/net/ice/ice_ethdev.c +++ b/drivers/net/ice/ice_ethdev.c @@ -2504,7 +2504,7 @@ ice_dev_init(struct rte_eth_dev *dev) hw->phy_model = ICE_PHY_E822; if (hw->phy_model == ICE_PHY_E822) { - ret = ice_start_phy_timer_e822(hw, hw->pf_id, true); + ret = ice_start_phy_timer_e822(hw, hw->pf_id); if (ret) PMD_INIT_LOG(ERR, "Failed to start phy timer\n"); } -- 2.43.0