Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / ethernet / mellanox / mlx5 / core / lib / clock.c
1 /*
2  * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <linux/clocksource.h>
34 #include <linux/highmem.h>
35 #include <rdma/mlx5-abi.h>
36 #include "lib/eq.h"
37 #include "en.h"
38 #include "clock.h"
39
40 enum {
41         MLX5_CYCLES_SHIFT       = 23
42 };
43
44 enum {
45         MLX5_PIN_MODE_IN                = 0x0,
46         MLX5_PIN_MODE_OUT               = 0x1,
47 };
48
49 enum {
50         MLX5_OUT_PATTERN_PULSE          = 0x0,
51         MLX5_OUT_PATTERN_PERIODIC       = 0x1,
52 };
53
54 enum {
55         MLX5_EVENT_MODE_DISABLE = 0x0,
56         MLX5_EVENT_MODE_REPETETIVE      = 0x1,
57         MLX5_EVENT_MODE_ONCE_TILL_ARM   = 0x2,
58 };
59
60 enum {
61         MLX5_MTPPS_FS_ENABLE                    = BIT(0x0),
62         MLX5_MTPPS_FS_PATTERN                   = BIT(0x2),
63         MLX5_MTPPS_FS_PIN_MODE                  = BIT(0x3),
64         MLX5_MTPPS_FS_TIME_STAMP                = BIT(0x4),
65         MLX5_MTPPS_FS_OUT_PULSE_DURATION        = BIT(0x5),
66         MLX5_MTPPS_FS_ENH_OUT_PER_ADJ           = BIT(0x7),
67 };
68
69 static u64 read_internal_timer(const struct cyclecounter *cc)
70 {
71         struct mlx5_clock *clock = container_of(cc, struct mlx5_clock, cycles);
72         struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
73                                                   clock);
74
75         return mlx5_read_internal_timer(mdev, NULL) & cc->mask;
76 }
77
78 static void mlx5_update_clock_info_page(struct mlx5_core_dev *mdev)
79 {
80         struct mlx5_ib_clock_info *clock_info = mdev->clock_info;
81         struct mlx5_clock *clock = &mdev->clock;
82         u32 sign;
83
84         if (!clock_info)
85                 return;
86
87         sign = smp_load_acquire(&clock_info->sign);
88         smp_store_mb(clock_info->sign,
89                      sign | MLX5_IB_CLOCK_INFO_KERNEL_UPDATING);
90
91         clock_info->cycles = clock->tc.cycle_last;
92         clock_info->mult   = clock->cycles.mult;
93         clock_info->nsec   = clock->tc.nsec;
94         clock_info->frac   = clock->tc.frac;
95
96         smp_store_release(&clock_info->sign,
97                           sign + MLX5_IB_CLOCK_INFO_KERNEL_UPDATING * 2);
98 }
99
100 static void mlx5_pps_out(struct work_struct *work)
101 {
102         struct mlx5_pps *pps_info = container_of(work, struct mlx5_pps,
103                                                  out_work);
104         struct mlx5_clock *clock = container_of(pps_info, struct mlx5_clock,
105                                                 pps_info);
106         struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
107                                                   clock);
108         u32 in[MLX5_ST_SZ_DW(mtpps_reg)] = {0};
109         unsigned long flags;
110         int i;
111
112         for (i = 0; i < clock->ptp_info.n_pins; i++) {
113                 u64 tstart;
114
115                 write_seqlock_irqsave(&clock->lock, flags);
116                 tstart = clock->pps_info.start[i];
117                 clock->pps_info.start[i] = 0;
118                 write_sequnlock_irqrestore(&clock->lock, flags);
119                 if (!tstart)
120                         continue;
121
122                 MLX5_SET(mtpps_reg, in, pin, i);
123                 MLX5_SET64(mtpps_reg, in, time_stamp, tstart);
124                 MLX5_SET(mtpps_reg, in, field_select, MLX5_MTPPS_FS_TIME_STAMP);
125                 mlx5_set_mtpps(mdev, in, sizeof(in));
126         }
127 }
128
129 static void mlx5_timestamp_overflow(struct work_struct *work)
130 {
131         struct delayed_work *dwork = to_delayed_work(work);
132         struct mlx5_clock *clock = container_of(dwork, struct mlx5_clock,
133                                                 overflow_work);
134         unsigned long flags;
135
136         write_seqlock_irqsave(&clock->lock, flags);
137         timecounter_read(&clock->tc);
138         mlx5_update_clock_info_page(clock->mdev);
139         write_sequnlock_irqrestore(&clock->lock, flags);
140         schedule_delayed_work(&clock->overflow_work, clock->overflow_period);
141 }
142
143 static int mlx5_ptp_settime(struct ptp_clock_info *ptp,
144                             const struct timespec64 *ts)
145 {
146         struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
147                                                  ptp_info);
148         u64 ns = timespec64_to_ns(ts);
149         unsigned long flags;
150
151         write_seqlock_irqsave(&clock->lock, flags);
152         timecounter_init(&clock->tc, &clock->cycles, ns);
153         mlx5_update_clock_info_page(clock->mdev);
154         write_sequnlock_irqrestore(&clock->lock, flags);
155
156         return 0;
157 }
158
159 static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
160                              struct ptp_system_timestamp *sts)
161 {
162         struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
163                                                 ptp_info);
164         struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
165                                                   clock);
166         unsigned long flags;
167         u64 cycles, ns;
168
169         write_seqlock_irqsave(&clock->lock, flags);
170         cycles = mlx5_read_internal_timer(mdev, sts);
171         ns = timecounter_cyc2time(&clock->tc, cycles);
172         write_sequnlock_irqrestore(&clock->lock, flags);
173
174         *ts = ns_to_timespec64(ns);
175
176         return 0;
177 }
178
179 static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
180 {
181         struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
182                                                 ptp_info);
183         unsigned long flags;
184
185         write_seqlock_irqsave(&clock->lock, flags);
186         timecounter_adjtime(&clock->tc, delta);
187         mlx5_update_clock_info_page(clock->mdev);
188         write_sequnlock_irqrestore(&clock->lock, flags);
189
190         return 0;
191 }
192
193 static int mlx5_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
194 {
195         u64 adj;
196         u32 diff;
197         unsigned long flags;
198         int neg_adj = 0;
199         struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
200                                                 ptp_info);
201
202         if (delta < 0) {
203                 neg_adj = 1;
204                 delta = -delta;
205         }
206
207         adj = clock->nominal_c_mult;
208         adj *= delta;
209         diff = div_u64(adj, 1000000000ULL);
210
211         write_seqlock_irqsave(&clock->lock, flags);
212         timecounter_read(&clock->tc);
213         clock->cycles.mult = neg_adj ? clock->nominal_c_mult - diff :
214                                        clock->nominal_c_mult + diff;
215         mlx5_update_clock_info_page(clock->mdev);
216         write_sequnlock_irqrestore(&clock->lock, flags);
217
218         return 0;
219 }
220
221 static int mlx5_extts_configure(struct ptp_clock_info *ptp,
222                                 struct ptp_clock_request *rq,
223                                 int on)
224 {
225         struct mlx5_clock *clock =
226                         container_of(ptp, struct mlx5_clock, ptp_info);
227         struct mlx5_core_dev *mdev =
228                         container_of(clock, struct mlx5_core_dev, clock);
229         u32 in[MLX5_ST_SZ_DW(mtpps_reg)] = {0};
230         u32 field_select = 0;
231         u8 pin_mode = 0;
232         u8 pattern = 0;
233         int pin = -1;
234         int err = 0;
235
236         if (!MLX5_PPS_CAP(mdev))
237                 return -EOPNOTSUPP;
238
239         if (rq->extts.index >= clock->ptp_info.n_pins)
240                 return -EINVAL;
241
242         if (on) {
243                 pin = ptp_find_pin(clock->ptp, PTP_PF_EXTTS, rq->extts.index);
244                 if (pin < 0)
245                         return -EBUSY;
246                 pin_mode = MLX5_PIN_MODE_IN;
247                 pattern = !!(rq->extts.flags & PTP_FALLING_EDGE);
248                 field_select = MLX5_MTPPS_FS_PIN_MODE |
249                                MLX5_MTPPS_FS_PATTERN |
250                                MLX5_MTPPS_FS_ENABLE;
251         } else {
252                 pin = rq->extts.index;
253                 field_select = MLX5_MTPPS_FS_ENABLE;
254         }
255
256         MLX5_SET(mtpps_reg, in, pin, pin);
257         MLX5_SET(mtpps_reg, in, pin_mode, pin_mode);
258         MLX5_SET(mtpps_reg, in, pattern, pattern);
259         MLX5_SET(mtpps_reg, in, enable, on);
260         MLX5_SET(mtpps_reg, in, field_select, field_select);
261
262         err = mlx5_set_mtpps(mdev, in, sizeof(in));
263         if (err)
264                 return err;
265
266         return mlx5_set_mtppse(mdev, pin, 0,
267                                MLX5_EVENT_MODE_REPETETIVE & on);
268 }
269
270 static int mlx5_perout_configure(struct ptp_clock_info *ptp,
271                                  struct ptp_clock_request *rq,
272                                  int on)
273 {
274         struct mlx5_clock *clock =
275                         container_of(ptp, struct mlx5_clock, ptp_info);
276         struct mlx5_core_dev *mdev =
277                         container_of(clock, struct mlx5_core_dev, clock);
278         u32 in[MLX5_ST_SZ_DW(mtpps_reg)] = {0};
279         u64 nsec_now, nsec_delta, time_stamp = 0;
280         u64 cycles_now, cycles_delta;
281         struct timespec64 ts;
282         unsigned long flags;
283         u32 field_select = 0;
284         u8 pin_mode = 0;
285         u8 pattern = 0;
286         int pin = -1;
287         int err = 0;
288         s64 ns;
289
290         if (!MLX5_PPS_CAP(mdev))
291                 return -EOPNOTSUPP;
292
293         if (rq->perout.index >= clock->ptp_info.n_pins)
294                 return -EINVAL;
295
296         if (on) {
297                 pin = ptp_find_pin(clock->ptp, PTP_PF_PEROUT,
298                                    rq->perout.index);
299                 if (pin < 0)
300                         return -EBUSY;
301
302                 pin_mode = MLX5_PIN_MODE_OUT;
303                 pattern = MLX5_OUT_PATTERN_PERIODIC;
304                 ts.tv_sec = rq->perout.period.sec;
305                 ts.tv_nsec = rq->perout.period.nsec;
306                 ns = timespec64_to_ns(&ts);
307
308                 if ((ns >> 1) != 500000000LL)
309                         return -EINVAL;
310
311                 ts.tv_sec = rq->perout.start.sec;
312                 ts.tv_nsec = rq->perout.start.nsec;
313                 ns = timespec64_to_ns(&ts);
314                 cycles_now = mlx5_read_internal_timer(mdev, NULL);
315                 write_seqlock_irqsave(&clock->lock, flags);
316                 nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
317                 nsec_delta = ns - nsec_now;
318                 cycles_delta = div64_u64(nsec_delta << clock->cycles.shift,
319                                          clock->cycles.mult);
320                 write_sequnlock_irqrestore(&clock->lock, flags);
321                 time_stamp = cycles_now + cycles_delta;
322                 field_select = MLX5_MTPPS_FS_PIN_MODE |
323                                MLX5_MTPPS_FS_PATTERN |
324                                MLX5_MTPPS_FS_ENABLE |
325                                MLX5_MTPPS_FS_TIME_STAMP;
326         } else {
327                 pin = rq->perout.index;
328                 field_select = MLX5_MTPPS_FS_ENABLE;
329         }
330
331         MLX5_SET(mtpps_reg, in, pin, pin);
332         MLX5_SET(mtpps_reg, in, pin_mode, pin_mode);
333         MLX5_SET(mtpps_reg, in, pattern, pattern);
334         MLX5_SET(mtpps_reg, in, enable, on);
335         MLX5_SET64(mtpps_reg, in, time_stamp, time_stamp);
336         MLX5_SET(mtpps_reg, in, field_select, field_select);
337
338         err = mlx5_set_mtpps(mdev, in, sizeof(in));
339         if (err)
340                 return err;
341
342         return mlx5_set_mtppse(mdev, pin, 0,
343                                MLX5_EVENT_MODE_REPETETIVE & on);
344 }
345
346 static int mlx5_pps_configure(struct ptp_clock_info *ptp,
347                               struct ptp_clock_request *rq,
348                               int on)
349 {
350         struct mlx5_clock *clock =
351                         container_of(ptp, struct mlx5_clock, ptp_info);
352
353         clock->pps_info.enabled = !!on;
354         return 0;
355 }
356
357 static int mlx5_ptp_enable(struct ptp_clock_info *ptp,
358                            struct ptp_clock_request *rq,
359                            int on)
360 {
361         switch (rq->type) {
362         case PTP_CLK_REQ_EXTTS:
363                 return mlx5_extts_configure(ptp, rq, on);
364         case PTP_CLK_REQ_PEROUT:
365                 return mlx5_perout_configure(ptp, rq, on);
366         case PTP_CLK_REQ_PPS:
367                 return mlx5_pps_configure(ptp, rq, on);
368         default:
369                 return -EOPNOTSUPP;
370         }
371         return 0;
372 }
373
374 static int mlx5_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
375                            enum ptp_pin_function func, unsigned int chan)
376 {
377         return (func == PTP_PF_PHYSYNC) ? -EOPNOTSUPP : 0;
378 }
379
380 static const struct ptp_clock_info mlx5_ptp_clock_info = {
381         .owner          = THIS_MODULE,
382         .name           = "mlx5_p2p",
383         .max_adj        = 100000000,
384         .n_alarm        = 0,
385         .n_ext_ts       = 0,
386         .n_per_out      = 0,
387         .n_pins         = 0,
388         .pps            = 0,
389         .adjfreq        = mlx5_ptp_adjfreq,
390         .adjtime        = mlx5_ptp_adjtime,
391         .gettimex64     = mlx5_ptp_gettimex,
392         .settime64      = mlx5_ptp_settime,
393         .enable         = NULL,
394         .verify         = NULL,
395 };
396
397 static int mlx5_init_pin_config(struct mlx5_clock *clock)
398 {
399         int i;
400
401         clock->ptp_info.pin_config =
402                         kcalloc(clock->ptp_info.n_pins,
403                                 sizeof(*clock->ptp_info.pin_config),
404                                 GFP_KERNEL);
405         if (!clock->ptp_info.pin_config)
406                 return -ENOMEM;
407         clock->ptp_info.enable = mlx5_ptp_enable;
408         clock->ptp_info.verify = mlx5_ptp_verify;
409         clock->ptp_info.pps = 1;
410
411         for (i = 0; i < clock->ptp_info.n_pins; i++) {
412                 snprintf(clock->ptp_info.pin_config[i].name,
413                          sizeof(clock->ptp_info.pin_config[i].name),
414                          "mlx5_pps%d", i);
415                 clock->ptp_info.pin_config[i].index = i;
416                 clock->ptp_info.pin_config[i].func = PTP_PF_NONE;
417                 clock->ptp_info.pin_config[i].chan = i;
418         }
419
420         return 0;
421 }
422
423 static void mlx5_get_pps_caps(struct mlx5_core_dev *mdev)
424 {
425         struct mlx5_clock *clock = &mdev->clock;
426         u32 out[MLX5_ST_SZ_DW(mtpps_reg)] = {0};
427
428         mlx5_query_mtpps(mdev, out, sizeof(out));
429
430         clock->ptp_info.n_pins = MLX5_GET(mtpps_reg, out,
431                                           cap_number_of_pps_pins);
432         clock->ptp_info.n_ext_ts = MLX5_GET(mtpps_reg, out,
433                                             cap_max_num_of_pps_in_pins);
434         clock->ptp_info.n_per_out = MLX5_GET(mtpps_reg, out,
435                                              cap_max_num_of_pps_out_pins);
436
437         clock->pps_info.pin_caps[0] = MLX5_GET(mtpps_reg, out, cap_pin_0_mode);
438         clock->pps_info.pin_caps[1] = MLX5_GET(mtpps_reg, out, cap_pin_1_mode);
439         clock->pps_info.pin_caps[2] = MLX5_GET(mtpps_reg, out, cap_pin_2_mode);
440         clock->pps_info.pin_caps[3] = MLX5_GET(mtpps_reg, out, cap_pin_3_mode);
441         clock->pps_info.pin_caps[4] = MLX5_GET(mtpps_reg, out, cap_pin_4_mode);
442         clock->pps_info.pin_caps[5] = MLX5_GET(mtpps_reg, out, cap_pin_5_mode);
443         clock->pps_info.pin_caps[6] = MLX5_GET(mtpps_reg, out, cap_pin_6_mode);
444         clock->pps_info.pin_caps[7] = MLX5_GET(mtpps_reg, out, cap_pin_7_mode);
445 }
446
447 static int mlx5_pps_event(struct notifier_block *nb,
448                           unsigned long type, void *data)
449 {
450         struct mlx5_clock *clock = mlx5_nb_cof(nb, struct mlx5_clock, pps_nb);
451         struct mlx5_core_dev *mdev = clock->mdev;
452         struct ptp_clock_event ptp_event;
453         u64 cycles_now, cycles_delta;
454         u64 nsec_now, nsec_delta, ns;
455         struct mlx5_eqe *eqe = data;
456         int pin = eqe->data.pps.pin;
457         struct timespec64 ts;
458         unsigned long flags;
459
460         switch (clock->ptp_info.pin_config[pin].func) {
461         case PTP_PF_EXTTS:
462                 ptp_event.index = pin;
463                 ptp_event.timestamp = timecounter_cyc2time(&clock->tc,
464                                         be64_to_cpu(eqe->data.pps.time_stamp));
465                 if (clock->pps_info.enabled) {
466                         ptp_event.type = PTP_CLOCK_PPSUSR;
467                         ptp_event.pps_times.ts_real =
468                                         ns_to_timespec64(ptp_event.timestamp);
469                 } else {
470                         ptp_event.type = PTP_CLOCK_EXTTS;
471                 }
472                 /* TODOL clock->ptp can be NULL if ptp_clock_register failes */
473                 ptp_clock_event(clock->ptp, &ptp_event);
474                 break;
475         case PTP_PF_PEROUT:
476                 mlx5_ptp_gettimex(&clock->ptp_info, &ts, NULL);
477                 cycles_now = mlx5_read_internal_timer(mdev, NULL);
478                 ts.tv_sec += 1;
479                 ts.tv_nsec = 0;
480                 ns = timespec64_to_ns(&ts);
481                 write_seqlock_irqsave(&clock->lock, flags);
482                 nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
483                 nsec_delta = ns - nsec_now;
484                 cycles_delta = div64_u64(nsec_delta << clock->cycles.shift,
485                                          clock->cycles.mult);
486                 clock->pps_info.start[pin] = cycles_now + cycles_delta;
487                 schedule_work(&clock->pps_info.out_work);
488                 write_sequnlock_irqrestore(&clock->lock, flags);
489                 break;
490         default:
491                 mlx5_core_err(mdev, " Unhandled clock PPS event, func %d\n",
492                               clock->ptp_info.pin_config[pin].func);
493         }
494
495         return NOTIFY_OK;
496 }
497
498 void mlx5_init_clock(struct mlx5_core_dev *mdev)
499 {
500         struct mlx5_clock *clock = &mdev->clock;
501         u64 overflow_cycles;
502         u64 ns;
503         u64 frac = 0;
504         u32 dev_freq;
505
506         dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz);
507         if (!dev_freq) {
508                 mlx5_core_warn(mdev, "invalid device_frequency_khz, aborting HW clock init\n");
509                 return;
510         }
511         seqlock_init(&clock->lock);
512         clock->cycles.read = read_internal_timer;
513         clock->cycles.shift = MLX5_CYCLES_SHIFT;
514         clock->cycles.mult = clocksource_khz2mult(dev_freq,
515                                                   clock->cycles.shift);
516         clock->nominal_c_mult = clock->cycles.mult;
517         clock->cycles.mask = CLOCKSOURCE_MASK(41);
518         clock->mdev = mdev;
519
520         timecounter_init(&clock->tc, &clock->cycles,
521                          ktime_to_ns(ktime_get_real()));
522
523         /* Calculate period in seconds to call the overflow watchdog - to make
524          * sure counter is checked at least twice every wrap around.
525          * The period is calculated as the minimum between max HW cycles count
526          * (The clock source mask) and max amount of cycles that can be
527          * multiplied by clock multiplier where the result doesn't exceed
528          * 64bits.
529          */
530         overflow_cycles = div64_u64(~0ULL >> 1, clock->cycles.mult);
531         overflow_cycles = min(overflow_cycles, div_u64(clock->cycles.mask, 3));
532
533         ns = cyclecounter_cyc2ns(&clock->cycles, overflow_cycles,
534                                  frac, &frac);
535         do_div(ns, NSEC_PER_SEC / HZ);
536         clock->overflow_period = ns;
537
538         mdev->clock_info =
539                 (struct mlx5_ib_clock_info *)get_zeroed_page(GFP_KERNEL);
540         if (mdev->clock_info) {
541                 mdev->clock_info->nsec = clock->tc.nsec;
542                 mdev->clock_info->cycles = clock->tc.cycle_last;
543                 mdev->clock_info->mask = clock->cycles.mask;
544                 mdev->clock_info->mult = clock->nominal_c_mult;
545                 mdev->clock_info->shift = clock->cycles.shift;
546                 mdev->clock_info->frac = clock->tc.frac;
547                 mdev->clock_info->overflow_period = clock->overflow_period;
548         }
549
550         INIT_WORK(&clock->pps_info.out_work, mlx5_pps_out);
551         INIT_DELAYED_WORK(&clock->overflow_work, mlx5_timestamp_overflow);
552         if (clock->overflow_period)
553                 schedule_delayed_work(&clock->overflow_work, 0);
554         else
555                 mlx5_core_warn(mdev, "invalid overflow period, overflow_work is not scheduled\n");
556
557         /* Configure the PHC */
558         clock->ptp_info = mlx5_ptp_clock_info;
559
560         /* Initialize 1PPS data structures */
561         if (MLX5_PPS_CAP(mdev))
562                 mlx5_get_pps_caps(mdev);
563         if (clock->ptp_info.n_pins)
564                 mlx5_init_pin_config(clock);
565
566         clock->ptp = ptp_clock_register(&clock->ptp_info,
567                                         &mdev->pdev->dev);
568         if (IS_ERR(clock->ptp)) {
569                 mlx5_core_warn(mdev, "ptp_clock_register failed %ld\n",
570                                PTR_ERR(clock->ptp));
571                 clock->ptp = NULL;
572         }
573
574         MLX5_NB_INIT(&clock->pps_nb, mlx5_pps_event, PPS_EVENT);
575         mlx5_eq_notifier_register(mdev, &clock->pps_nb);
576 }
577
578 void mlx5_cleanup_clock(struct mlx5_core_dev *mdev)
579 {
580         struct mlx5_clock *clock = &mdev->clock;
581
582         if (!MLX5_CAP_GEN(mdev, device_frequency_khz))
583                 return;
584
585         mlx5_eq_notifier_unregister(mdev, &clock->pps_nb);
586         if (clock->ptp) {
587                 ptp_clock_unregister(clock->ptp);
588                 clock->ptp = NULL;
589         }
590
591         cancel_work_sync(&clock->pps_info.out_work);
592         cancel_delayed_work_sync(&clock->overflow_work);
593
594         if (mdev->clock_info) {
595                 free_page((unsigned long)mdev->clock_info);
596                 mdev->clock_info = NULL;
597         }
598
599         kfree(clock->ptp_info.pin_config);
600 }