1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PTP virtual clock driver
7 #include <linux/slab.h>
8 #include <linux/hashtable.h>
9 #include "ptp_private.h"
11 #define PTP_VCLOCK_CC_SHIFT 31
12 #define PTP_VCLOCK_CC_MULT (1 << PTP_VCLOCK_CC_SHIFT)
13 #define PTP_VCLOCK_FADJ_SHIFT 9
14 #define PTP_VCLOCK_FADJ_DENOMINATOR 15625ULL
15 #define PTP_VCLOCK_REFRESH_INTERVAL (HZ * 2)
17 /* protects vclock_hash addition/deletion */
18 static DEFINE_SPINLOCK(vclock_hash_lock
);
20 static DEFINE_READ_MOSTLY_HASHTABLE(vclock_hash
, 8);
22 static void ptp_vclock_hash_add(struct ptp_vclock
*vclock
)
24 spin_lock(&vclock_hash_lock
);
26 hlist_add_head_rcu(&vclock
->vclock_hash_node
,
27 &vclock_hash
[vclock
->clock
->index
% HASH_SIZE(vclock_hash
)]);
29 spin_unlock(&vclock_hash_lock
);
32 static void ptp_vclock_hash_del(struct ptp_vclock
*vclock
)
34 spin_lock(&vclock_hash_lock
);
36 hlist_del_init_rcu(&vclock
->vclock_hash_node
);
38 spin_unlock(&vclock_hash_lock
);
43 static int ptp_vclock_adjfine(struct ptp_clock_info
*ptp
, long scaled_ppm
)
45 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
48 adj
= (s64
)scaled_ppm
<< PTP_VCLOCK_FADJ_SHIFT
;
49 adj
= div_s64(adj
, PTP_VCLOCK_FADJ_DENOMINATOR
);
51 if (mutex_lock_interruptible(&vclock
->lock
))
53 timecounter_read(&vclock
->tc
);
54 vclock
->cc
.mult
= PTP_VCLOCK_CC_MULT
+ adj
;
55 mutex_unlock(&vclock
->lock
);
60 static int ptp_vclock_adjtime(struct ptp_clock_info
*ptp
, s64 delta
)
62 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
64 if (mutex_lock_interruptible(&vclock
->lock
))
66 timecounter_adjtime(&vclock
->tc
, delta
);
67 mutex_unlock(&vclock
->lock
);
72 static int ptp_vclock_gettime(struct ptp_clock_info
*ptp
,
73 struct timespec64
*ts
)
75 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
78 if (mutex_lock_interruptible(&vclock
->lock
))
80 ns
= timecounter_read(&vclock
->tc
);
81 mutex_unlock(&vclock
->lock
);
82 *ts
= ns_to_timespec64(ns
);
87 static int ptp_vclock_gettimex(struct ptp_clock_info
*ptp
,
88 struct timespec64
*ts
,
89 struct ptp_system_timestamp
*sts
)
91 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
92 struct ptp_clock
*pptp
= vclock
->pclock
;
93 struct timespec64 pts
;
97 err
= pptp
->info
->getcyclesx64(pptp
->info
, &pts
, sts
);
101 if (mutex_lock_interruptible(&vclock
->lock
))
103 ns
= timecounter_cyc2time(&vclock
->tc
, timespec64_to_ns(&pts
));
104 mutex_unlock(&vclock
->lock
);
106 *ts
= ns_to_timespec64(ns
);
111 static int ptp_vclock_settime(struct ptp_clock_info
*ptp
,
112 const struct timespec64
*ts
)
114 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
115 u64 ns
= timespec64_to_ns(ts
);
117 if (mutex_lock_interruptible(&vclock
->lock
))
119 timecounter_init(&vclock
->tc
, &vclock
->cc
, ns
);
120 mutex_unlock(&vclock
->lock
);
125 static int ptp_vclock_getcrosststamp(struct ptp_clock_info
*ptp
,
126 struct system_device_crosststamp
*xtstamp
)
128 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
129 struct ptp_clock
*pptp
= vclock
->pclock
;
133 err
= pptp
->info
->getcrosscycles(pptp
->info
, xtstamp
);
137 if (mutex_lock_interruptible(&vclock
->lock
))
139 ns
= timecounter_cyc2time(&vclock
->tc
, ktime_to_ns(xtstamp
->device
));
140 mutex_unlock(&vclock
->lock
);
142 xtstamp
->device
= ns_to_ktime(ns
);
147 static long ptp_vclock_refresh(struct ptp_clock_info
*ptp
)
149 struct ptp_vclock
*vclock
= info_to_vclock(ptp
);
150 struct timespec64 ts
;
152 ptp_vclock_gettime(&vclock
->info
, &ts
);
154 return PTP_VCLOCK_REFRESH_INTERVAL
;
157 static const struct ptp_clock_info ptp_vclock_info
= {
158 .owner
= THIS_MODULE
,
159 .name
= "ptp virtual clock",
160 .max_adj
= 500000000,
161 .adjfine
= ptp_vclock_adjfine
,
162 .adjtime
= ptp_vclock_adjtime
,
163 .settime64
= ptp_vclock_settime
,
164 .do_aux_work
= ptp_vclock_refresh
,
167 static u64
ptp_vclock_read(const struct cyclecounter
*cc
)
169 struct ptp_vclock
*vclock
= cc_to_vclock(cc
);
170 struct ptp_clock
*ptp
= vclock
->pclock
;
171 struct timespec64 ts
= {};
173 ptp
->info
->getcycles64(ptp
->info
, &ts
);
175 return timespec64_to_ns(&ts
);
178 static const struct cyclecounter ptp_vclock_cc
= {
179 .read
= ptp_vclock_read
,
180 .mask
= CYCLECOUNTER_MASK(32),
181 .mult
= PTP_VCLOCK_CC_MULT
,
182 .shift
= PTP_VCLOCK_CC_SHIFT
,
185 struct ptp_vclock
*ptp_vclock_register(struct ptp_clock
*pclock
)
187 struct ptp_vclock
*vclock
;
189 vclock
= kzalloc(sizeof(*vclock
), GFP_KERNEL
);
193 vclock
->pclock
= pclock
;
194 vclock
->info
= ptp_vclock_info
;
195 if (pclock
->info
->getcyclesx64
)
196 vclock
->info
.gettimex64
= ptp_vclock_gettimex
;
198 vclock
->info
.gettime64
= ptp_vclock_gettime
;
199 if (pclock
->info
->getcrosscycles
)
200 vclock
->info
.getcrosststamp
= ptp_vclock_getcrosststamp
;
201 vclock
->cc
= ptp_vclock_cc
;
203 snprintf(vclock
->info
.name
, PTP_CLOCK_NAME_LEN
, "ptp%d_virt",
206 INIT_HLIST_NODE(&vclock
->vclock_hash_node
);
208 mutex_init(&vclock
->lock
);
210 vclock
->clock
= ptp_clock_register(&vclock
->info
, &pclock
->dev
);
211 if (IS_ERR_OR_NULL(vclock
->clock
)) {
216 timecounter_init(&vclock
->tc
, &vclock
->cc
, 0);
217 ptp_schedule_worker(vclock
->clock
, PTP_VCLOCK_REFRESH_INTERVAL
);
219 ptp_vclock_hash_add(vclock
);
224 void ptp_vclock_unregister(struct ptp_vclock
*vclock
)
226 ptp_vclock_hash_del(vclock
);
228 ptp_clock_unregister(vclock
->clock
);
232 #if IS_BUILTIN(CONFIG_PTP_1588_CLOCK)
233 int ptp_get_vclocks_index(int pclock_index
, int **vclock_index
)
235 char name
[PTP_CLOCK_NAME_LEN
] = "";
236 struct ptp_clock
*ptp
;
240 if (pclock_index
< 0)
243 snprintf(name
, PTP_CLOCK_NAME_LEN
, "ptp%d", pclock_index
);
244 dev
= class_find_device_by_name(&ptp_class
, name
);
248 ptp
= dev_get_drvdata(dev
);
250 if (mutex_lock_interruptible(&ptp
->n_vclocks_mux
)) {
255 *vclock_index
= kzalloc(sizeof(int) * ptp
->n_vclocks
, GFP_KERNEL
);
256 if (!(*vclock_index
))
259 memcpy(*vclock_index
, ptp
->vclock_index
, sizeof(int) * ptp
->n_vclocks
);
260 num
= ptp
->n_vclocks
;
262 mutex_unlock(&ptp
->n_vclocks_mux
);
266 EXPORT_SYMBOL(ptp_get_vclocks_index
);
268 ktime_t
ptp_convert_timestamp(const ktime_t
*hwtstamp
, int vclock_index
)
270 unsigned int hash
= vclock_index
% HASH_SIZE(vclock_hash
);
271 struct ptp_vclock
*vclock
;
275 ns
= ktime_to_ns(*hwtstamp
);
279 hlist_for_each_entry_rcu(vclock
, &vclock_hash
[hash
], vclock_hash_node
) {
280 if (vclock
->clock
->index
!= vclock_index
)
283 if (mutex_lock_interruptible(&vclock
->lock
))
285 vclock_ns
= timecounter_cyc2time(&vclock
->tc
, ns
);
286 mutex_unlock(&vclock
->lock
);
292 return ns_to_ktime(vclock_ns
);
294 EXPORT_SYMBOL(ptp_convert_timestamp
);