Skip to content

Commit d17125f

Browse files
Binary-Eaterkuba-moo
authored andcommitted
net/mlx5: Implement PTM cross timestamping support
Expose Precision Time Measurement support through related PTP ioctl. The performance of PTM on ConnectX-7 was evaluated using both real-time (RTC) and free-running (FRC) clocks under traffic and no traffic conditions. Tests with phc2sys measured the maximum offset values at a 50Hz rate, with and without PTM. Results: 1. No traffic +-----+--------+--------+ | | No-PTM | PTM | +-----+--------+--------+ | FRC | 125 ns | <29 ns | +-----+--------+--------+ | RTC | 248 ns | <34 ns | +-----+--------+--------+ 2. With traffic +-----+--------+--------+ | | No-PTM | PTM | +-----+--------+--------+ | FRC | 254 ns | <40 ns | +-----+--------+--------+ | RTC | 255 ns | <45 ns | +-----+--------+--------+ Signed-off-by: Rahul Rameshbabu <[email protected]> Co-developed-by: Carolina Jubran <[email protected]> Signed-off-by: Carolina Jubran <[email protected]> Signed-off-by: Tariq Toukan <[email protected]> Reviewed-by: Wojciech Drewek <[email protected]> Tested-by: Vadim Fedorenko <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent bec6d85 commit d17125f

File tree

1 file changed

+91
-0
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core/lib

1 file changed

+91
-0
lines changed

drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
#include "lib/eq.h"
3939
#include "en.h"
4040
#include "clock.h"
41+
#ifdef CONFIG_X86
42+
#include <linux/timekeeping.h>
43+
#include <linux/cpufeature.h>
44+
#endif /* CONFIG_X86 */
4145

4246
enum {
4347
MLX5_PIN_MODE_IN = 0x0,
@@ -148,6 +152,87 @@ static int mlx5_set_mtutc(struct mlx5_core_dev *dev, u32 *mtutc, u32 size)
148152
MLX5_REG_MTUTC, 0, 1);
149153
}
150154

155+
#ifdef CONFIG_X86
156+
static bool mlx5_is_ptm_source_time_available(struct mlx5_core_dev *dev)
157+
{
158+
u32 out[MLX5_ST_SZ_DW(mtptm_reg)] = {0};
159+
u32 in[MLX5_ST_SZ_DW(mtptm_reg)] = {0};
160+
int err;
161+
162+
if (!MLX5_CAP_MCAM_REG3(dev, mtptm))
163+
return false;
164+
165+
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MTPTM,
166+
0, 0);
167+
if (err)
168+
return false;
169+
170+
return !!MLX5_GET(mtptm_reg, out, psta);
171+
}
172+
173+
static int mlx5_mtctr_syncdevicetime(ktime_t *device_time,
174+
struct system_counterval_t *sys_counterval,
175+
void *ctx)
176+
{
177+
u32 out[MLX5_ST_SZ_DW(mtctr_reg)] = {0};
178+
u32 in[MLX5_ST_SZ_DW(mtctr_reg)] = {0};
179+
struct mlx5_core_dev *mdev = ctx;
180+
bool real_time_mode;
181+
u64 host, device;
182+
int err;
183+
184+
real_time_mode = mlx5_real_time_mode(mdev);
185+
186+
MLX5_SET(mtctr_reg, in, first_clock_timestamp_request,
187+
MLX5_MTCTR_REQUEST_PTM_ROOT_CLOCK);
188+
MLX5_SET(mtctr_reg, in, second_clock_timestamp_request,
189+
real_time_mode ? MLX5_MTCTR_REQUEST_REAL_TIME_CLOCK :
190+
MLX5_MTCTR_REQUEST_FREE_RUNNING_COUNTER);
191+
192+
err = mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_MTCTR,
193+
0, 0);
194+
if (err)
195+
return err;
196+
197+
if (!MLX5_GET(mtctr_reg, out, first_clock_valid) ||
198+
!MLX5_GET(mtctr_reg, out, second_clock_valid))
199+
return -EINVAL;
200+
201+
host = MLX5_GET64(mtctr_reg, out, first_clock_timestamp);
202+
*sys_counterval = (struct system_counterval_t) {
203+
.cycles = host,
204+
.cs_id = CSID_X86_ART,
205+
.use_nsecs = true,
206+
};
207+
208+
device = MLX5_GET64(mtctr_reg, out, second_clock_timestamp);
209+
if (real_time_mode)
210+
*device_time = ns_to_ktime(REAL_TIME_TO_NS(device >> 32, device & U32_MAX));
211+
else
212+
*device_time = mlx5_timecounter_cyc2time(&mdev->clock, device);
213+
214+
return 0;
215+
}
216+
217+
static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp,
218+
struct system_device_crosststamp *cts)
219+
{
220+
struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
221+
struct system_time_snapshot history_begin = {0};
222+
struct mlx5_core_dev *mdev;
223+
224+
mdev = container_of(clock, struct mlx5_core_dev, clock);
225+
226+
if (!mlx5_is_ptm_source_time_available(mdev))
227+
return -EBUSY;
228+
229+
ktime_get_snapshot(&history_begin);
230+
231+
return get_device_system_crosststamp(mlx5_mtctr_syncdevicetime, mdev,
232+
&history_begin, cts);
233+
}
234+
#endif /* CONFIG_X86 */
235+
151236
static u64 mlx5_read_time(struct mlx5_core_dev *dev,
152237
struct ptp_system_timestamp *sts,
153238
bool real_time)
@@ -1034,6 +1119,12 @@ static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev)
10341119
if (MLX5_CAP_MCAM_REG(mdev, mtutc))
10351120
mlx5_init_timer_max_freq_adjustment(mdev);
10361121

1122+
#ifdef CONFIG_X86
1123+
if (MLX5_CAP_MCAM_REG3(mdev, mtptm) &&
1124+
MLX5_CAP_MCAM_REG3(mdev, mtctr) && boot_cpu_has(X86_FEATURE_ART))
1125+
clock->ptp_info.getcrosststamp = mlx5_ptp_getcrosststamp;
1126+
#endif /* CONFIG_X86 */
1127+
10371128
mlx5_timecounter_init(mdev);
10381129
mlx5_init_clock_info(mdev);
10391130
mlx5_init_overflow_period(clock);

0 commit comments

Comments
 (0)