From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

Change-Id: Ie8085815bfdd054de0649ceb9790b36a5beb9ca5
---
 .../ethernet/mellanox/mlx5/core/lib/clock.c   | 200 ++++++++++++++++--
 1 file changed, 184 insertions(+), 16 deletions(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -39,6 +39,10 @@
 #include "en.h"
 #include "clock.h"
 
+#ifndef smp_store_mb
+#define smp_store_mb set_mb
+#endif
+
 enum {
 	MLX5_PIN_MODE_IN		= 0x0,
 	MLX5_PIN_MODE_OUT		= 0x1,
@@ -149,25 +153,37 @@ static int mlx5_set_mtutc(struct mlx5_co
 }
 
 static u64 mlx5_read_time(struct mlx5_core_dev *dev,
+#ifdef HAVE_GETTIMEX64
 			  struct ptp_system_timestamp *sts,
+#else
+			  void *sts,
+#endif
 			  bool real_time)
 {
 	u32 timer_h, timer_h1, timer_l;
 
 	timer_h = ioread32be(real_time ? &dev->iseg->real_time_h :
 			     &dev->iseg->internal_timer_h);
+#ifdef HAVE_GETTIMEX64
 	ptp_read_system_prets(sts);
+#endif
 	timer_l = ioread32be(real_time ? &dev->iseg->real_time_l :
 			     &dev->iseg->internal_timer_l);
+#ifdef HAVE_GETTIMEX64
 	ptp_read_system_postts(sts);
+#endif
 	timer_h1 = ioread32be(real_time ? &dev->iseg->real_time_h :
 			      &dev->iseg->internal_timer_h);
 	if (timer_h != timer_h1) {
 		/* wrap around */
+#ifdef HAVE_GETTIMEX64
 		ptp_read_system_prets(sts);
+#endif
 		timer_l = ioread32be(real_time ? &dev->iseg->real_time_l :
 				     &dev->iseg->internal_timer_l);
+#ifdef HAVE_GETTIMEX64
 		ptp_read_system_postts(sts);
+#endif
 	}
 
 	return real_time ? REAL_TIME_TO_NS(timer_h1, timer_l) :
@@ -190,14 +206,12 @@ static void mlx5_update_clock_info_page(
 	struct mlx5_clock *clock = &mdev->clock;
 	struct mlx5_timer *timer;
 	u32 sign;
-
 	if (!clock_info)
 		return;
 
 	sign = smp_load_acquire(&clock_info->sign);
 	smp_store_mb(clock_info->sign,
 		     sign | MLX5_IB_CLOCK_INFO_KERNEL_UPDATING);
-
 	timer = &clock->timer;
 	clock_info->cycles = timer->tc.cycle_last;
 	clock_info->mult   = timer->cycles.mult;
@@ -208,6 +222,7 @@ static void mlx5_update_clock_info_page(
 			  sign + MLX5_IB_CLOCK_INFO_KERNEL_UPDATING * 2);
 }
 
+#if defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)
 static void mlx5_pps_out(struct work_struct *work)
 {
 	struct mlx5_pps *pps_info = container_of(work, struct mlx5_pps,
@@ -236,6 +251,7 @@ static void mlx5_pps_out(struct work_str
 		mlx5_set_mtpps(mdev, in, sizeof(in));
 	}
 }
+#endif
 
 static void mlx5_timestamp_overflow(struct work_struct *work)
 {
@@ -261,6 +277,7 @@ out:
 	schedule_delayed_work(&timer->overflow_work, timer->overflow_period);
 }
 
+#if (defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE))
 static int mlx5_ptp_settime_real_time(struct mlx5_core_dev *mdev,
 				      const struct timespec64 *ts)
 {
@@ -277,7 +294,8 @@ static int mlx5_ptp_settime_real_time(st
 	return mlx5_set_mtutc(mdev, in, sizeof(in));
 }
 
-static int mlx5_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)
+static int mlx5_ptp_settime(struct ptp_clock_info *ptp,
+			    const struct timespec64 *ts)
 {
 	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
 	struct mlx5_timer *timer = &clock->timer;
@@ -300,10 +318,13 @@ static int mlx5_ptp_settime(struct ptp_c
 
 	return 0;
 }
-
 static
 struct timespec64 mlx5_ptp_gettimex_real_time(struct mlx5_core_dev *mdev,
+#ifdef HAVE_GETTIMEX64
 					      struct ptp_system_timestamp *sts)
+#else
+						  void *sts)
+#endif
 {
 	struct timespec64 ts;
 	u64 time;
@@ -313,8 +334,10 @@ struct timespec64 mlx5_ptp_gettimex_real
 	return ts;
 }
 
-static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
-			     struct ptp_system_timestamp *sts)
+#ifdef HAVE_GETTIMEX64
+static int mlx5_ptp_gettimex(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_timer *timer = &clock->timer;
@@ -336,7 +359,33 @@ static int mlx5_ptp_gettimex(struct ptp_
 out:
 	return 0;
 }
+#else/*HAVE_GETTIMEX64*/
+static int mlx5_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
+			ptp_info);
+	struct mlx5_timer *timer = &clock->timer;
+	struct mlx5_core_dev *mdev;
+	unsigned long flags;
+	u64 cycles, ns;
+
+	mdev = container_of(clock, struct mlx5_core_dev, clock);
+	if (mlx5_real_time_mode(mdev)) {
+		*ts = mlx5_ptp_gettimex_real_time(mdev, NULL);
+		goto out;
+	}
 
+	write_seqlock_irqsave(&clock->lock, flags);
+	cycles = mlx5_read_time(mdev, NULL, false);
+	ns = timecounter_read(&timer->tc);
+	write_sequnlock_irqrestore(&clock->lock, flags);
+
+	*ts = ns_to_timespec64(ns);
+
+out:
+	return 0;
+}
+#endif/*HAVE_GETTIMEX64*/
 static int mlx5_ptp_adjtime_real_time(struct mlx5_core_dev *mdev, s64 delta)
 {
 	u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {};
@@ -382,6 +431,7 @@ static int mlx5_ptp_adjtime(struct ptp_c
 	return 0;
 }
 
+#ifdef HAVE_PTP_CLOCK_INFO_ADJPHASE
 static int mlx5_ptp_adjphase(struct ptp_clock_info *ptp, s32 delta)
 {
 	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
@@ -391,6 +441,7 @@ static int mlx5_ptp_adjphase(struct ptp_
 
 	return mlx5_ptp_adjtime_real_time(mdev, delta);
 }
+#endif
 
 static int mlx5_ptp_freq_adj_real_time(struct mlx5_core_dev *mdev, long scaled_ppm)
 {
@@ -398,6 +449,7 @@ static int mlx5_ptp_freq_adj_real_time(s
 
 	MLX5_SET(mtutc_reg, in, operation, MLX5_MTUTC_OPERATION_ADJUST_FREQ_UTC);
 
+#ifdef HAVE_ADJUST_BY_SCALED_PPM
 	if (MLX5_CAP_MCAM_FEATURE(mdev, mtutc_freq_adj_units) &&
 	    scaled_ppm <= S32_MAX && scaled_ppm >= S32_MIN) {
 		/* HW scaled_ppm support on mlx5 devices only supports a 32-bit value */
@@ -408,10 +460,54 @@ static int mlx5_ptp_freq_adj_real_time(s
 		MLX5_SET(mtutc_reg, in, freq_adj_units, MLX5_MTUTC_FREQ_ADJ_UNITS_PPB);
 		MLX5_SET(mtutc_reg, in, freq_adjustment, scaled_ppm_to_ppb(scaled_ppm));
 	}
+#else
+		MLX5_SET(mtutc_reg, in, freq_adjustment, scaled_ppm);
+#endif
+
 
 	return mlx5_set_mtutc(mdev, in, sizeof(in));
 }
 
+#ifdef HAVE_PTP_CLOCK_INFO_NDO_ADJFREQ
+static int mlx5_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
+{
+	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
+	struct mlx5_timer *timer = &clock->timer;
+	struct mlx5_core_dev *mdev;
+	unsigned long flags;
+	int neg_adj = 0;
+	u32 diff;
+	u64 adj;
+
+	mdev = container_of(clock, struct mlx5_core_dev, clock);
+	if (mlx5_modify_mtutc_allowed(mdev)) {
+		int err = mlx5_ptp_freq_adj_real_time(mdev, delta);
+
+		if (err)
+			return err;
+	}
+
+	if (delta < 0) {
+		neg_adj = 1;
+		delta = -delta;
+	}
+
+	adj = timer->nominal_c_mult;
+	adj *= delta;
+	diff = div_u64(adj, 1000000000ULL);
+
+	write_seqlock_irqsave(&clock->lock, flags);
+	timecounter_read(&timer->tc);
+	timer->cycles.mult = neg_adj ? timer->nominal_c_mult - diff :
+				       timer->nominal_c_mult + diff;
+	mlx5_update_clock_info_page(mdev);
+	write_sequnlock_irqrestore(&clock->lock, flags);
+
+	return 0;
+}
+#endif
+
+#if defined(HAVE_ADJUST_BY_SCALED_PPM)
 static int mlx5_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
@@ -439,6 +535,33 @@ static int mlx5_ptp_adjfine(struct ptp_c
 
 	return 0;
 }
+#endif
+
+#ifndef PTP_STRICT_FLAGS
+#define PTP_STRICT_FLAGS   (1<<3)
+#endif
+#ifndef PTP_EXTTS_EDGES
+#define PTP_EXTTS_EDGES    (PTP_RISING_EDGE | PTP_FALLING_EDGE)
+#endif
+
+#ifndef HAVE_PTP_FIND_PIN_UNLOCK
+static int mlx5_ptp_find_pin(struct mlx5_clock *clock,
+		enum ptp_pin_function func,
+		unsigned int chan, int on)
+{
+	int i;
+
+	if (on)
+		return ptp_find_pin(clock->ptp, func, chan);
+
+	for (i = 0; i < clock->ptp_info.n_pins; i++) {
+		if (clock->ptp_info.pin_config[i].func == func &&
+				clock->ptp_info.pin_config[i].chan == chan)
+			return i;
+	}
+	return -1;
+}
+#endif
 
 static int mlx5_extts_configure(struct ptp_clock_info *ptp,
 				struct ptp_clock_request *rq,
@@ -474,7 +597,12 @@ static int mlx5_extts_configure(struct p
 	if (rq->extts.index >= clock->ptp_info.n_pins)
 		return -EINVAL;
 
+#ifdef HAVE_PTP_FIND_PIN_UNLOCK
 	pin = ptp_find_pin(clock->ptp, PTP_PF_EXTTS, rq->extts.index);
+#else
+	pin = mlx5_ptp_find_pin(clock, PTP_PF_EXTTS, rq->extts.index, on);
+#endif
+
 	if (pin < 0)
 		return -EBUSY;
 
@@ -542,13 +670,12 @@ static u64 perout_conf_real_time(s64 sec
 static int perout_conf_1pps(struct mlx5_core_dev *mdev, struct ptp_clock_request *rq,
 			    u64 *time_stamp, bool real_time)
 {
-	struct timespec64 ts;
+ 	struct timespec64 ts;
 	s64 ns;
 
 	ts.tv_nsec = rq->perout.period.nsec;
 	ts.tv_sec = rq->perout.period.sec;
 	ns = timespec64_to_ns(&ts);
-
 	if ((ns >> 1) != 500000000LL)
 		return -EINVAL;
 
@@ -565,20 +692,24 @@ static int mlx5_perout_conf_out_pulse_du
 {
 	struct mlx5_pps *pps_info = &mdev->clock.pps_info;
 	u32 out_pulse_duration;
-	struct timespec64 ts;
+ 	struct timespec64 ts;
 
+#ifdef HAVE_PTP_PEROUT_DUTY_CYCLE
 	if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) {
 		ts.tv_sec = rq->perout.on.sec;
 		ts.tv_nsec = rq->perout.on.nsec;
 		out_pulse_duration = (u32)timespec64_to_ns(&ts);
 	} else {
+#endif
 		/* out_pulse_duration_ns should be up to 50% of the
 		 * pulse period as default
 		 */
 		ts.tv_sec = rq->perout.period.sec;
 		ts.tv_nsec = rq->perout.period.nsec;
 		out_pulse_duration = (u32)timespec64_to_ns(&ts) >> 1;
+#ifdef HAVE_PTP_PEROUT_DUTY_CYCLE
 	}
+#endif
 
 	if (out_pulse_duration < pps_info->min_out_pulse_duration_ns ||
 	    out_pulse_duration > MLX5_MAX_PULSE_DURATION) {
@@ -619,11 +750,12 @@ static int perout_conf_npps_real_time(st
 	return 0;
 }
 
+#ifdef HAVE_PTP_PEROUT_DUTY_CYCLE
 static bool mlx5_perout_verify_flags(struct mlx5_core_dev *mdev, unsigned int flags)
 {
-	return ((!mlx5_npps_real_time_supported(mdev) && flags) ||
-		(mlx5_npps_real_time_supported(mdev) && flags & ~PTP_PEROUT_DUTY_CYCLE));
+	return ((!mlx5_npps_real_time_supported(mdev) && flags) || (mlx5_npps_real_time_supported(mdev) && flags & ~PTP_PEROUT_DUTY_CYCLE));
 }
+#endif
 
 static int mlx5_perout_configure(struct ptp_clock_info *ptp,
 				 struct ptp_clock_request *rq,
@@ -648,14 +780,23 @@ static int mlx5_perout_configure(struct
 		return -EOPNOTSUPP;
 
 	/* Reject requests with unsupported flags */
+#ifdef HAVE_PTP_PEROUT_DUTY_CYCLE
 	if (mlx5_perout_verify_flags(mdev, rq->perout.flags))
+#else
+	if (rq->perout.flags)
+#endif
 		return -EOPNOTSUPP;
 
 	if (rq->perout.index >= clock->ptp_info.n_pins)
 		return -EINVAL;
 
 	field_select = MLX5_MTPPS_FS_ENABLE;
+#ifdef HAVE_PTP_FIND_PIN_UNLOCK
 	pin = ptp_find_pin(clock->ptp, PTP_PF_PEROUT, rq->perout.index);
+#else
+	pin = mlx5_ptp_find_pin(clock, PTP_PF_PEROUT, rq->perout.index, on);
+#endif
+
 	if (pin < 0)
 		return -EBUSY;
 
@@ -763,12 +904,26 @@ static const struct ptp_clock_info mlx5_
 	.n_per_out	= 0,
 	.n_pins		= 0,
 	.pps		= 0,
+#ifdef HAVE_PTP_CLOCK_INFO_NDO_ADJFREQ
+	.adjfreq	= mlx5_ptp_adjfreq,
+#endif
+#if defined(HAVE_ADJUST_BY_SCALED_PPM)
 	.adjfine	= mlx5_ptp_adjfine,
+#endif
+#ifdef HAVE_PTP_CLOCK_INFO_ADJPHASE
 	.adjphase	= mlx5_ptp_adjphase,
+#endif
+#ifdef HAVE_PTP_CLOCK_INFO_NDO_GETMAXPHASE
 	.getmaxphase    = mlx5_ptp_getmaxphase,
+#endif
 	.adjtime	= mlx5_ptp_adjtime,
+#ifdef HAVE_GETTIMEX64
 	.gettimex64	= mlx5_ptp_gettimex,
 	.settime64	= mlx5_ptp_settime,
+#else /*HAVE_GETTIMEX64*/
+	.gettime64      = mlx5_ptp_gettime,
+	.settime64      = mlx5_ptp_settime,
+#endif /*HAVE_GETTIMEX64*/
 	.enable		= NULL,
 	.verify		= NULL,
 };
@@ -873,10 +1028,14 @@ static void ts_next_sec(struct timespec6
 static u64 perout_conf_next_event_timer(struct mlx5_core_dev *mdev,
 					struct mlx5_clock *clock)
 {
-	struct timespec64 ts;
+       struct timespec64 ts;
 	s64 target_ns;
 
+#ifdef HAVE_GETTIMEX64
 	mlx5_ptp_gettimex(&clock->ptp_info, &ts, NULL);
+#else
+	mlx5_ptp_gettime(&clock->ptp_info, &ts);
+#endif
 	ts_next_sec(&ts);
 	target_ns = timespec64_to_ns(&ts);
 
@@ -893,7 +1052,6 @@ static int mlx5_pps_event(struct notifie
 	struct mlx5_core_dev *mdev;
 	unsigned long flags;
 	u64 ns;
-
 	mdev = container_of(clock, struct mlx5_core_dev, clock);
 
 	switch (clock->ptp_info.pin_config[pin].func) {
@@ -928,6 +1086,7 @@ static int mlx5_pps_event(struct notifie
 
 	return NOTIFY_OK;
 }
+#endif /* (CONFIG_PTP_1588_CLOCK || CONFIG_PTP_1588_CLOCK_MODULE) */
 
 static void mlx5_timecounter_init(struct mlx5_core_dev *mdev)
 {
@@ -965,7 +1124,6 @@ static void mlx5_init_overflow_period(st
 	 */
 	overflow_cycles = div64_u64(~0ULL >> 1, timer->cycles.mult);
 	overflow_cycles = min(overflow_cycles, div_u64(timer->cycles.mask, 3));
-
 	ns = cyclecounter_cyc2ns(&timer->cycles, overflow_cycles,
 				 frac, &frac);
 	do_div(ns, NSEC_PER_SEC / HZ);
@@ -1067,8 +1225,11 @@ void mlx5_init_clock(struct mlx5_core_de
 	}
 
 	seqlock_init(&clock->lock);
+#if defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)
 	INIT_WORK(&clock->pps_info.out_work, mlx5_pps_out);
+#endif
 
+#if (defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE))
 	/* Initialize the device clock */
 	mlx5_init_timer_clock(mdev);
 
@@ -1082,9 +1243,11 @@ void mlx5_init_clock(struct mlx5_core_de
 			       PTR_ERR(clock->ptp));
 		clock->ptp = NULL;
 	}
-
+#endif
+#if defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)
 	MLX5_NB_INIT(&clock->pps_nb, mlx5_pps_event, PPS_EVENT);
 	mlx5_eq_notifier_register(mdev, &clock->pps_nb);
+#endif
 }
 
 void mlx5_cleanup_clock(struct mlx5_core_dev *mdev)
@@ -1095,12 +1258,15 @@ void mlx5_cleanup_clock(struct mlx5_core
 		return;
 
 	mlx5_eq_notifier_unregister(mdev, &clock->pps_nb);
+#if (defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE))
 	if (clock->ptp) {
 		ptp_clock_unregister(clock->ptp);
 		clock->ptp = NULL;
 	}
-
+#endif
+#if defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)
 	cancel_work_sync(&clock->pps_info.out_work);
+#endif
 	cancel_delayed_work_sync(&clock->timer.overflow_work);
 
 	if (mdev->clock_info) {
@@ -1108,5 +1274,7 @@ void mlx5_cleanup_clock(struct mlx5_core
 		mdev->clock_info = NULL;
 	}
 
+#if defined (CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)
 	kfree(clock->ptp_info.pin_config);
+#endif
 }
