OSDN Git Service

mlx5: extend PTP gettime function to read system clock
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 3 Dec 2018 12:59:42 +0000 (13:59 +0100)
committerSaeed Mahameed <saeedm@mellanox.com>
Thu, 20 Dec 2018 13:06:00 +0000 (05:06 -0800)
Read the system time right before and immediately after reading the low
register of the internal timer. This adds support for the
PTP_SYS_OFFSET_EXTENDED ioctl.

Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h

index 53f021d..ca0ee99 100644 (file)
@@ -72,7 +72,7 @@ static u64 read_internal_timer(const struct cyclecounter *cc)
        struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
                                                  clock);
 
-       return mlx5_read_internal_timer(mdev) & cc->mask;
+       return mlx5_read_internal_timer(mdev, NULL) & cc->mask;
 }
 
 static void mlx5_update_clock_info_page(struct mlx5_core_dev *mdev)
@@ -156,15 +156,19 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp,
        return 0;
 }
 
-static int mlx5_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+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);
-       u64 ns;
+       struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
+                                                 clock);
        unsigned long flags;
+       u64 cycles, ns;
 
        write_seqlock_irqsave(&clock->lock, flags);
-       ns = timecounter_read(&clock->tc);
+       cycles = mlx5_read_internal_timer(mdev, sts);
+       ns = timecounter_cyc2time(&clock->tc, cycles);
        write_sequnlock_irqrestore(&clock->lock, flags);
 
        *ts = ns_to_timespec64(ns);
@@ -307,7 +311,7 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp,
                ts.tv_sec = rq->perout.start.sec;
                ts.tv_nsec = rq->perout.start.nsec;
                ns = timespec64_to_ns(&ts);
-               cycles_now = mlx5_read_internal_timer(mdev);
+               cycles_now = mlx5_read_internal_timer(mdev, NULL);
                write_seqlock_irqsave(&clock->lock, flags);
                nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
                nsec_delta = ns - nsec_now;
@@ -384,7 +388,7 @@ static const struct ptp_clock_info mlx5_ptp_clock_info = {
        .pps            = 0,
        .adjfreq        = mlx5_ptp_adjfreq,
        .adjtime        = mlx5_ptp_adjtime,
-       .gettime64      = mlx5_ptp_gettime,
+       .gettimex64     = mlx5_ptp_gettimex,
        .settime64      = mlx5_ptp_settime,
        .enable         = NULL,
        .verify         = NULL,
@@ -469,8 +473,8 @@ static int mlx5_pps_event(struct notifier_block *nb,
                ptp_clock_event(clock->ptp, &ptp_event);
                break;
        case PTP_PF_PEROUT:
-               mlx5_ptp_gettime(&clock->ptp_info, &ts);
-               cycles_now = mlx5_read_internal_timer(mdev);
+               mlx5_ptp_gettimex(&clock->ptp_info, &ts, NULL);
+               cycles_now = mlx5_read_internal_timer(mdev, NULL);
                ts.tv_sec += 1;
                ts.tv_nsec = 0;
                ns = timespec64_to_ns(&ts);
index c235531..77896c1 100644 (file)
@@ -580,15 +580,22 @@ int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id)
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
 
-u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev)
+u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
+                            struct ptp_system_timestamp *sts)
 {
        u32 timer_h, timer_h1, timer_l;
 
        timer_h = ioread32be(&dev->iseg->internal_timer_h);
+       ptp_read_system_prets(sts);
        timer_l = ioread32be(&dev->iseg->internal_timer_l);
+       ptp_read_system_postts(sts);
        timer_h1 = ioread32be(&dev->iseg->internal_timer_h);
-       if (timer_h != timer_h1) /* wrap around */
+       if (timer_h != timer_h1) {
+               /* wrap around */
+               ptp_read_system_prets(sts);
                timer_l = ioread32be(&dev->iseg->internal_timer_l);
+               ptp_read_system_postts(sts);
+       }
 
        return (u64)timer_l | (u64)timer_h1 << 32;
 }
index 73bf465..c68dcea 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/sched.h>
 #include <linux/if_link.h>
 #include <linux/firmware.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/mlx5/cq.h>
 #include <linux/mlx5/fs.h>
 
@@ -121,7 +122,8 @@ int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
 int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
                                        u32 element_id);
 int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev);
-u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev);
+u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
+                            struct ptp_system_timestamp *sts);
 
 void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev);
 int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev);