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 } 601