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.

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: Siddaraju DH <siddaraju...@intel.com>
Signed-off-by: Jacob Keller <jacob.e.kel...@intel.com>
Signed-off-by: Anatoly Burakov <anatoly.bura...@intel.com>
---
 drivers/net/ice/base/ice_ptp_hw.c | 67 +++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ice/base/ice_ptp_hw.c 
b/drivers/net/ice/base/ice_ptp_hw.c
index f775575de3..b340b4aa6d 100644
--- a/drivers/net/ice/base/ice_ptp_hw.c
+++ b/drivers/net/ice/base/ice_ptp_hw.c
@@ -3890,14 +3890,19 @@ ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum 
ice_ptp_link_spd link_spd)
  * adjust Tx timestamps by. This is calculated by combining some known static
  * latency along with the Vernier offset computations done by hardware.
  *
- * This function must be called only after the offset registers are valid,
- * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
- * has measured the offset.
+ * This function will not return successfully until the Tx offset calculations
+ * have been completed, which requires waiting until at least one packet has
+ * been transmitted by the device. It is safe to call this function
+ * periodically until calibration succeeds, as it will only program the offset
+ * once.
  *
  * To avoid overflow, when calculating the offset based on the known static
  * latency values, we use measurements in 1/100th of a nanosecond, and divide
  * the TUs per second up front. This avoids overflow while allowing
  * calculation of the adjustment using integer arithmetic.
+ *
+ * Returns zero on success, ICE_ERR_NOT_READY if the hardware vernier offset
+ * calibration has not completed, or another error code on failure.
  */
 int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
 {
@@ -3905,6 +3910,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, &reg);
+       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, &reg);
+       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)
@@ -3957,6 +3984,8 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
        if (err)
                return err;
 
+       ice_info(hw, "Port=%d Tx vernier offset calibration complete\n", port);
+
        return 0;
 }
 
@@ -4162,6 +4191,11 @@ ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum 
ice_ptp_link_spd link_spd)
  * measurements taken in hardware with some data about known fixed delay as
  * well as adjusting for multi-lane alignment delay.
  *
+ * This function will not return successfully until the Rx offset calculations
+ * have been completed, which requires waiting until at least one packet has
+ * been received by the device. It is safe to call this function periodically
+ * until calibration succeeds, as it will only program the offset once.
+ *
  * This function must be called only after the offset registers are valid,
  * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
  * has measured the offset.
@@ -4170,6 +4204,9 @@ ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum 
ice_ptp_link_spd link_spd)
  * latency values, we use measurements in 1/100th of a nanosecond, and divide
  * the TUs per second up front. This avoids overflow while allowing
  * calculation of the adjustment using integer arithmetic.
+ *
+ * Returns zero on success, ICE_ERR_NOT_READY if the hardware vernier offset
+ * calibration has not completed, or another error code on failure.
  */
 int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
 {
@@ -4177,6 +4214,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, &reg);
+       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, &reg);
+       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)
@@ -4237,6 +4296,8 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
        if (err)
                return err;
 
+       ice_info(hw, "Port=%d Rx vernier offset calibration complete\n", port);
+
        return 0;
 }
 
-- 
2.43.0

Reply via email to