net/mlx5e: Eliminate build warnings on no previous prototype
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / lib / clock.c
index 5701f125e99c10afc45fc431bb53a6855cd216cc..857035583ccdd156c7913c001c1509e0cde044bb 100644 (file)
  */
 
 #include <linux/clocksource.h>
+#include <linux/highmem.h>
+#include <rdma/mlx5-abi.h>
 #include "en.h"
+#include "clock.h"
 
 enum {
        MLX5_CYCLES_SHIFT       = 23
@@ -71,6 +74,28 @@ static u64 read_internal_timer(const struct cyclecounter *cc)
        return mlx5_read_internal_timer(mdev) & cc->mask;
 }
 
+static void mlx5_update_clock_info_page(struct mlx5_core_dev *mdev)
+{
+       struct mlx5_ib_clock_info *clock_info = mdev->clock_info;
+       struct mlx5_clock *clock = &mdev->clock;
+       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);
+
+       clock_info->cycles = clock->tc.cycle_last;
+       clock_info->mult   = clock->cycles.mult;
+       clock_info->nsec   = clock->tc.nsec;
+       clock_info->frac   = clock->tc.frac;
+
+       smp_store_release(&clock_info->sign,
+                         sign + MLX5_IB_CLOCK_INFO_KERNEL_UPDATING * 2);
+}
+
 static void mlx5_pps_out(struct work_struct *work)
 {
        struct mlx5_pps *pps_info = container_of(work, struct mlx5_pps,
@@ -109,6 +134,7 @@ static void mlx5_timestamp_overflow(struct work_struct *work)
 
        write_lock_irqsave(&clock->lock, flags);
        timecounter_read(&clock->tc);
+       mlx5_update_clock_info_page(clock->mdev);
        write_unlock_irqrestore(&clock->lock, flags);
        schedule_delayed_work(&clock->overflow_work, clock->overflow_period);
 }
@@ -123,6 +149,7 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp,
 
        write_lock_irqsave(&clock->lock, flags);
        timecounter_init(&clock->tc, &clock->cycles, ns);
+       mlx5_update_clock_info_page(clock->mdev);
        write_unlock_irqrestore(&clock->lock, flags);
 
        return 0;
@@ -152,6 +179,7 @@ static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 
        write_lock_irqsave(&clock->lock, flags);
        timecounter_adjtime(&clock->tc, delta);
+       mlx5_update_clock_info_page(clock->mdev);
        write_unlock_irqrestore(&clock->lock, flags);
 
        return 0;
@@ -179,6 +207,7 @@ static int mlx5_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
        timecounter_read(&clock->tc);
        clock->cycles.mult = neg_adj ? clock->nominal_c_mult - diff :
                                       clock->nominal_c_mult + diff;
+       mlx5_update_clock_info_page(clock->mdev);
        write_unlock_irqrestore(&clock->lock, flags);
 
        return 0;
@@ -474,6 +503,7 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
                                                  clock->cycles.shift);
        clock->nominal_c_mult = clock->cycles.mult;
        clock->cycles.mask = CLOCKSOURCE_MASK(41);
+       clock->mdev = mdev;
 
        timecounter_init(&clock->tc, &clock->cycles,
                         ktime_to_ns(ktime_get_real()));
@@ -486,6 +516,25 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
        do_div(ns, NSEC_PER_SEC / 2 / HZ);
        clock->overflow_period = ns;
 
+       mdev->clock_info_page = alloc_page(GFP_KERNEL);
+       if (mdev->clock_info_page) {
+               mdev->clock_info = kmap(mdev->clock_info_page);
+               if (!mdev->clock_info) {
+                       __free_page(mdev->clock_info_page);
+                       mlx5_core_warn(mdev, "failed to map clock page\n");
+               } else {
+                       mdev->clock_info->sign   = 0;
+                       mdev->clock_info->nsec   = clock->tc.nsec;
+                       mdev->clock_info->cycles = clock->tc.cycle_last;
+                       mdev->clock_info->mask   = clock->cycles.mask;
+                       mdev->clock_info->mult   = clock->nominal_c_mult;
+                       mdev->clock_info->shift  = clock->cycles.shift;
+                       mdev->clock_info->frac   = clock->tc.frac;
+                       mdev->clock_info->overflow_period =
+                                               clock->overflow_period;
+               }
+       }
+
        INIT_WORK(&clock->pps_info.out_work, mlx5_pps_out);
        INIT_DELAYED_WORK(&clock->overflow_work, mlx5_timestamp_overflow);
        if (clock->overflow_period)
@@ -525,5 +574,12 @@ void mlx5_cleanup_clock(struct mlx5_core_dev *mdev)
 
        cancel_work_sync(&clock->pps_info.out_work);
        cancel_delayed_work_sync(&clock->overflow_work);
+
+       if (mdev->clock_info) {
+               kunmap(mdev->clock_info_page);
+               __free_page(mdev->clock_info_page);
+               mdev->clock_info = NULL;
+       }
+
        kfree(clock->ptp_info.pin_config);
 }