|
38 | 38 | #include "lib/eq.h"
|
39 | 39 | #include "en.h"
|
40 | 40 | #include "clock.h"
|
| 41 | +#ifdef CONFIG_X86 |
| 42 | +#include <linux/timekeeping.h> |
| 43 | +#include <linux/cpufeature.h> |
| 44 | +#endif /* CONFIG_X86 */ |
41 | 45 |
|
42 | 46 | enum {
|
43 | 47 | MLX5_PIN_MODE_IN = 0x0,
|
@@ -148,6 +152,87 @@ static int mlx5_set_mtutc(struct mlx5_core_dev *dev, u32 *mtutc, u32 size)
|
148 | 152 | MLX5_REG_MTUTC, 0, 1);
|
149 | 153 | }
|
150 | 154 |
|
| 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 | + |
151 | 236 | static u64 mlx5_read_time(struct mlx5_core_dev *dev,
|
152 | 237 | struct ptp_system_timestamp *sts,
|
153 | 238 | bool real_time)
|
@@ -1034,6 +1119,12 @@ static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev)
|
1034 | 1119 | if (MLX5_CAP_MCAM_REG(mdev, mtutc))
|
1035 | 1120 | mlx5_init_timer_max_freq_adjustment(mdev);
|
1036 | 1121 |
|
| 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 | + |
1037 | 1128 | mlx5_timecounter_init(mdev);
|
1038 | 1129 | mlx5_init_clock_info(mdev);
|
1039 | 1130 | mlx5_init_overflow_period(clock);
|
|
0 commit comments