1 | /* |
2 | * Copyright (c) 2017, Mellanox Technologies, Ltd. 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 | #ifndef __LIB_CLOCK_H__ |
34 | #define __LIB_CLOCK_H__ |
35 | |
36 | static inline bool mlx5_is_real_time_rq(struct mlx5_core_dev *mdev) |
37 | { |
38 | u8 rq_ts_format_cap = MLX5_CAP_GEN(mdev, rq_ts_format); |
39 | |
40 | return (rq_ts_format_cap == MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME || |
41 | rq_ts_format_cap == |
42 | MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME); |
43 | } |
44 | |
45 | static inline bool mlx5_is_real_time_sq(struct mlx5_core_dev *mdev) |
46 | { |
47 | u8 sq_ts_format_cap = MLX5_CAP_GEN(mdev, sq_ts_format); |
48 | |
49 | return (sq_ts_format_cap == MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME || |
50 | sq_ts_format_cap == |
51 | MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME); |
52 | } |
53 | |
54 | typedef ktime_t (*cqe_ts_to_ns)(struct mlx5_clock *, u64); |
55 | |
56 | #if IS_ENABLED(CONFIG_PTP_1588_CLOCK) |
57 | void mlx5_init_clock(struct mlx5_core_dev *mdev); |
58 | void mlx5_cleanup_clock(struct mlx5_core_dev *mdev); |
59 | |
60 | static inline int mlx5_clock_get_ptp_index(struct mlx5_core_dev *mdev) |
61 | { |
62 | return mdev->clock.ptp ? ptp_clock_index(ptp: mdev->clock.ptp) : -1; |
63 | } |
64 | |
65 | static inline ktime_t mlx5_timecounter_cyc2time(struct mlx5_clock *clock, |
66 | u64 timestamp) |
67 | { |
68 | struct mlx5_timer *timer = &clock->timer; |
69 | unsigned int seq; |
70 | u64 nsec; |
71 | |
72 | do { |
73 | seq = read_seqbegin(sl: &clock->lock); |
74 | nsec = timecounter_cyc2time(tc: &timer->tc, cycle_tstamp: timestamp); |
75 | } while (read_seqretry(sl: &clock->lock, start: seq)); |
76 | |
77 | return ns_to_ktime(ns: nsec); |
78 | } |
79 | |
80 | #define REAL_TIME_TO_NS(hi, low) (((u64)hi) * NSEC_PER_SEC + ((u64)low)) |
81 | |
82 | static inline ktime_t mlx5_real_time_cyc2time(struct mlx5_clock *clock, |
83 | u64 timestamp) |
84 | { |
85 | u64 time = REAL_TIME_TO_NS(timestamp >> 32, timestamp & 0xFFFFFFFF); |
86 | |
87 | return ns_to_ktime(ns: time); |
88 | } |
89 | #else |
90 | static inline void mlx5_init_clock(struct mlx5_core_dev *mdev) {} |
91 | static inline void mlx5_cleanup_clock(struct mlx5_core_dev *mdev) {} |
92 | static inline int mlx5_clock_get_ptp_index(struct mlx5_core_dev *mdev) |
93 | { |
94 | return -1; |
95 | } |
96 | |
97 | static inline ktime_t mlx5_timecounter_cyc2time(struct mlx5_clock *clock, |
98 | u64 timestamp) |
99 | { |
100 | return 0; |
101 | } |
102 | |
103 | static inline ktime_t mlx5_real_time_cyc2time(struct mlx5_clock *clock, |
104 | u64 timestamp) |
105 | { |
106 | return 0; |
107 | } |
108 | #endif |
109 | |
110 | static inline cqe_ts_to_ns mlx5_rq_ts_translator(struct mlx5_core_dev *mdev) |
111 | { |
112 | return mlx5_is_real_time_rq(mdev) ? mlx5_real_time_cyc2time : |
113 | mlx5_timecounter_cyc2time; |
114 | } |
115 | |
116 | static inline cqe_ts_to_ns mlx5_sq_ts_translator(struct mlx5_core_dev *mdev) |
117 | { |
118 | return mlx5_is_real_time_sq(mdev) ? mlx5_real_time_cyc2time : |
119 | mlx5_timecounter_cyc2time; |
120 | } |
121 | #endif |
122 | |