net/mlx5: Move some PPS logic into helper functions

Some of PPS logic (timestamp calculations) fits only internal timer
timestamp mode. Move these logics into helper functions. Later in the
patchset cyc2time HW translation mode will expose its own PPS timestamp
calculations.

With this change, main flow will only hold calling PPS logic based on run
time mode.

Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Aya Levin <ayal@nvidia.com>
Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
Eran Ben Elisha 2021-02-12 14:30:41 -08:00 коммит произвёл Saeed Mahameed
Родитель d6f3dc8f50
Коммит de19cd6cc9
1 изменённых файлов: 73 добавлений и 40 удалений

Просмотреть файл

@ -314,6 +314,40 @@ static int mlx5_extts_configure(struct ptp_clock_info *ptp,
MLX5_EVENT_MODE_REPETETIVE & on); MLX5_EVENT_MODE_REPETETIVE & on);
} }
static u64 find_target_cycles(struct mlx5_core_dev *mdev, s64 target_ns)
{
struct mlx5_clock *clock = &mdev->clock;
u64 cycles_now, cycles_delta;
u64 nsec_now, nsec_delta;
struct mlx5_timer *timer;
unsigned long flags;
timer = &clock->timer;
cycles_now = mlx5_read_internal_timer(mdev, NULL);
write_seqlock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&timer->tc, cycles_now);
nsec_delta = target_ns - nsec_now;
cycles_delta = div64_u64(nsec_delta << timer->cycles.shift,
timer->cycles.mult);
write_sequnlock_irqrestore(&clock->lock, flags);
return cycles_now + cycles_delta;
}
static u64 perout_conf_internal_timer(struct mlx5_core_dev *mdev,
s64 sec, u32 nsec)
{
struct timespec64 ts;
s64 target_ns;
ts.tv_sec = sec;
ts.tv_nsec = nsec;
target_ns = timespec64_to_ns(&ts);
return find_target_cycles(mdev, target_ns);
}
static int mlx5_perout_configure(struct ptp_clock_info *ptp, static int mlx5_perout_configure(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, struct ptp_clock_request *rq,
int on) int on)
@ -322,13 +356,10 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp,
container_of(ptp, struct mlx5_clock, ptp_info); container_of(ptp, struct mlx5_clock, ptp_info);
struct mlx5_core_dev *mdev = struct mlx5_core_dev *mdev =
container_of(clock, struct mlx5_core_dev, clock); container_of(clock, struct mlx5_core_dev, clock);
struct mlx5_timer *timer = &clock->timer;
u32 in[MLX5_ST_SZ_DW(mtpps_reg)] = {0}; u32 in[MLX5_ST_SZ_DW(mtpps_reg)] = {0};
u64 nsec_now, nsec_delta, time_stamp = 0;
u64 cycles_now, cycles_delta;
struct timespec64 ts; struct timespec64 ts;
unsigned long flags;
u32 field_select = 0; u32 field_select = 0;
u64 time_stamp = 0;
u8 pin_mode = 0; u8 pin_mode = 0;
u8 pattern = 0; u8 pattern = 0;
int pin = -1; int pin = -1;
@ -345,12 +376,15 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp,
if (rq->perout.index >= clock->ptp_info.n_pins) if (rq->perout.index >= clock->ptp_info.n_pins)
return -EINVAL; return -EINVAL;
pin = ptp_find_pin(clock->ptp, PTP_PF_PEROUT, field_select = MLX5_MTPPS_FS_ENABLE;
rq->perout.index);
if (pin < 0)
return -EBUSY;
if (on) { if (on) {
u32 nsec;
s64 sec;
pin = ptp_find_pin(clock->ptp, PTP_PF_PEROUT, rq->perout.index);
if (pin < 0)
return -EBUSY;
pin_mode = MLX5_PIN_MODE_OUT; pin_mode = MLX5_PIN_MODE_OUT;
pattern = MLX5_OUT_PATTERN_PERIODIC; pattern = MLX5_OUT_PATTERN_PERIODIC;
ts.tv_sec = rq->perout.period.sec; ts.tv_sec = rq->perout.period.sec;
@ -360,23 +394,14 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp,
if ((ns >> 1) != 500000000LL) if ((ns >> 1) != 500000000LL)
return -EINVAL; return -EINVAL;
ts.tv_sec = rq->perout.start.sec; nsec = rq->perout.start.nsec;
ts.tv_nsec = rq->perout.start.nsec; sec = rq->perout.start.sec;
ns = timespec64_to_ns(&ts);
cycles_now = mlx5_read_internal_timer(mdev, NULL); time_stamp = perout_conf_internal_timer(mdev, sec, nsec);
write_seqlock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&timer->tc, cycles_now); field_select |= MLX5_MTPPS_FS_PIN_MODE |
nsec_delta = ns - nsec_now; MLX5_MTPPS_FS_PATTERN |
cycles_delta = div64_u64(nsec_delta << timer->cycles.shift, MLX5_MTPPS_FS_TIME_STAMP;
timer->cycles.mult);
write_sequnlock_irqrestore(&clock->lock, flags);
time_stamp = cycles_now + cycles_delta;
field_select = MLX5_MTPPS_FS_PIN_MODE |
MLX5_MTPPS_FS_PATTERN |
MLX5_MTPPS_FS_ENABLE |
MLX5_MTPPS_FS_TIME_STAMP;
} else {
field_select = MLX5_MTPPS_FS_ENABLE;
} }
MLX5_SET(mtpps_reg, in, pin, pin); MLX5_SET(mtpps_reg, in, pin, pin);
@ -547,19 +572,35 @@ static void mlx5_get_pps_caps(struct mlx5_core_dev *mdev)
clock->pps_info.pin_caps[7] = MLX5_GET(mtpps_reg, out, cap_pin_7_mode); clock->pps_info.pin_caps[7] = MLX5_GET(mtpps_reg, out, cap_pin_7_mode);
} }
static void ts_next_sec(struct timespec64 *ts)
{
ts->tv_sec += 1;
ts->tv_nsec = 0;
}
static u64 perout_conf_next_event_inernal_timer(struct mlx5_core_dev *mdev,
struct mlx5_clock *clock)
{
struct timespec64 ts;
s64 target_ns;
mlx5_ptp_gettimex(&clock->ptp_info, &ts, NULL);
ts_next_sec(&ts);
target_ns = timespec64_to_ns(&ts);
return find_target_cycles(mdev, target_ns);
}
static int mlx5_pps_event(struct notifier_block *nb, static int mlx5_pps_event(struct notifier_block *nb,
unsigned long type, void *data) unsigned long type, void *data)
{ {
struct mlx5_clock *clock = mlx5_nb_cof(nb, struct mlx5_clock, pps_nb); struct mlx5_clock *clock = mlx5_nb_cof(nb, struct mlx5_clock, pps_nb);
struct mlx5_timer *timer = &clock->timer;
struct ptp_clock_event ptp_event; struct ptp_clock_event ptp_event;
u64 cycles_now, cycles_delta;
u64 nsec_now, nsec_delta, ns;
struct mlx5_eqe *eqe = data; struct mlx5_eqe *eqe = data;
int pin = eqe->data.pps.pin; int pin = eqe->data.pps.pin;
struct mlx5_core_dev *mdev; struct mlx5_core_dev *mdev;
struct timespec64 ts;
unsigned long flags; unsigned long flags;
u64 ns;
mdev = container_of(clock, struct mlx5_core_dev, clock); mdev = container_of(clock, struct mlx5_core_dev, clock);
@ -580,17 +621,9 @@ static int mlx5_pps_event(struct notifier_block *nb,
ptp_clock_event(clock->ptp, &ptp_event); ptp_clock_event(clock->ptp, &ptp_event);
break; break;
case PTP_PF_PEROUT: case PTP_PF_PEROUT:
mlx5_ptp_gettimex(&clock->ptp_info, &ts, NULL); ns = perout_conf_next_event_inernal_timer(mdev, clock);
cycles_now = mlx5_read_internal_timer(mdev, NULL);
ts.tv_sec += 1;
ts.tv_nsec = 0;
ns = timespec64_to_ns(&ts);
write_seqlock_irqsave(&clock->lock, flags); write_seqlock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&timer->tc, cycles_now); clock->pps_info.start[pin] = ns;
nsec_delta = ns - nsec_now;
cycles_delta = div64_u64(nsec_delta << timer->cycles.shift,
timer->cycles.mult);
clock->pps_info.start[pin] = cycles_now + cycles_delta;
write_sequnlock_irqrestore(&clock->lock, flags); write_sequnlock_irqrestore(&clock->lock, flags);
schedule_work(&clock->pps_info.out_work); schedule_work(&clock->pps_info.out_work);
break; break;