From: Carolina Jubran Implement the getcyclesx64 and getcrosscycles callbacks in ptp_info to expose the device’s raw free-running counter. Signed-off-by: Carolina Jubran Reviewed-by: Dragos Tatulea Signed-off-by: Tariq Toukan --- .../ethernet/mellanox/mlx5/core/lib/clock.c | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index b1e2deeefc0c..2f75726674a9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -306,6 +306,23 @@ static int mlx5_mtctr_syncdevicetime(ktime_t *device_time, return 0; } +static int +mlx5_mtctr_syncdevicecyclestime(ktime_t *device_time, + struct system_counterval_t *sys_counterval, + void *ctx) +{ + struct mlx5_core_dev *mdev = ctx; + u64 device; + int err; + + err = mlx5_mtctr_read(mdev, false, sys_counterval, &device); + if (err) + return err; + *device_time = ns_to_ktime(device); + + return 0; +} + static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp, struct system_device_crosststamp *cts) { @@ -330,6 +347,32 @@ static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp, mlx5_clock_unlock(clock); return err; } + +static int mlx5_ptp_getcrosscycles(struct ptp_clock_info *ptp, + struct system_device_crosststamp *cts) +{ + struct mlx5_clock *clock = + container_of(ptp, struct mlx5_clock, ptp_info); + struct system_time_snapshot history_begin = {0}; + struct mlx5_core_dev *mdev; + int err; + + mlx5_clock_lock(clock); + mdev = mlx5_clock_mdev_get(clock); + + if (!mlx5_is_ptm_source_time_available(mdev)) { + err = -EBUSY; + goto unlock; + } + + ktime_get_snapshot(&history_begin); + + err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime, + mdev, &history_begin, cts); +unlock: + mlx5_clock_unlock(clock); + return err; +} #endif /* CONFIG_X86 */ static u64 mlx5_read_time(struct mlx5_core_dev *dev, @@ -528,6 +571,24 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, return 0; } +static int mlx5_ptp_getcyclesx(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, + ptp_info); + struct mlx5_core_dev *mdev; + u64 cycles; + + mlx5_clock_lock(clock); + mdev = mlx5_clock_mdev_get(clock); + + cycles = mlx5_read_time(mdev, sts, false); + *ts = ns_to_timespec64(cycles); + mlx5_clock_unlock(clock); + return 0; +} + static int mlx5_ptp_adjtime_real_time(struct mlx5_core_dev *mdev, s64 delta) { u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {}; @@ -1244,6 +1305,7 @@ static void mlx5_init_timer_max_freq_adjustment(struct mlx5_core_dev *mdev) static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev) { struct mlx5_clock *clock = mdev->clock; + bool expose_cycles; /* Configure the PHC */ clock->ptp_info = mlx5_ptp_clock_info; @@ -1251,12 +1313,22 @@ static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev) if (MLX5_CAP_MCAM_REG(mdev, mtutc)) mlx5_init_timer_max_freq_adjustment(mdev); + expose_cycles = !MLX5_CAP_GEN(mdev, disciplined_fr_counter) || + !mlx5_real_time_mode(mdev); + #ifdef CONFIG_X86 if (MLX5_CAP_MCAM_REG3(mdev, mtptm) && - MLX5_CAP_MCAM_REG3(mdev, mtctr) && boot_cpu_has(X86_FEATURE_ART)) + MLX5_CAP_MCAM_REG3(mdev, mtctr) && boot_cpu_has(X86_FEATURE_ART)) { clock->ptp_info.getcrosststamp = mlx5_ptp_getcrosststamp; + if (expose_cycles) + clock->ptp_info.getcrosscycles = + mlx5_ptp_getcrosscycles; + } #endif /* CONFIG_X86 */ + if (expose_cycles) + clock->ptp_info.getcyclesx64 = mlx5_ptp_getcyclesx; + mlx5_timecounter_init(mdev); mlx5_init_clock_info(mdev); mlx5_init_overflow_period(mdev); -- 2.31.1