xref: /linux/drivers/net/ethernet/google/gve/gve_ptp.c (revision 6f7e6393d1ce636bb7ec77a7fe7b77458fddf701)
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Google virtual Ethernet (gve) driver
3  *
4  * Copyright (C) 2025 Google LLC
5  */
6 
7 #include "gve.h"
8 #include "gve_adminq.h"
9 
10 /* Interval to schedule a nic timestamp calibration, 250ms. */
11 #define GVE_NIC_TS_SYNC_INTERVAL_MS 250
12 
13 /* Read the nic timestamp from hardware via the admin queue. */
14 int gve_clock_nic_ts_read(struct gve_priv *priv)
15 {
16 	u64 nic_raw;
17 	int err;
18 
19 	err = gve_adminq_report_nic_ts(priv, priv->nic_ts_report_bus);
20 	if (err)
21 		return err;
22 
23 	nic_raw = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
24 	WRITE_ONCE(priv->last_sync_nic_counter, nic_raw);
25 
26 	return 0;
27 }
28 
29 static int gve_ptp_gettimex64(struct ptp_clock_info *info,
30 			      struct timespec64 *ts,
31 			      struct ptp_system_timestamp *sts)
32 {
33 	return -EOPNOTSUPP;
34 }
35 
36 static int gve_ptp_settime64(struct ptp_clock_info *info,
37 			     const struct timespec64 *ts)
38 {
39 	return -EOPNOTSUPP;
40 }
41 
42 static long gve_ptp_do_aux_work(struct ptp_clock_info *info)
43 {
44 	const struct gve_ptp *ptp = container_of(info, struct gve_ptp, info);
45 	struct gve_priv *priv = ptp->priv;
46 	int err;
47 
48 	if (gve_get_reset_in_progress(priv) || !gve_get_admin_queue_ok(priv))
49 		goto out;
50 
51 	err = gve_clock_nic_ts_read(priv);
52 	if (err && net_ratelimit())
53 		dev_err(&priv->pdev->dev,
54 			"%s read err %d\n", __func__, err);
55 
56 out:
57 	return msecs_to_jiffies(GVE_NIC_TS_SYNC_INTERVAL_MS);
58 }
59 
60 static const struct ptp_clock_info gve_ptp_caps = {
61 	.owner          = THIS_MODULE,
62 	.name		= "gve clock",
63 	.gettimex64	= gve_ptp_gettimex64,
64 	.settime64	= gve_ptp_settime64,
65 	.do_aux_work	= gve_ptp_do_aux_work,
66 };
67 
68 static int gve_ptp_init(struct gve_priv *priv)
69 {
70 	struct gve_ptp *ptp;
71 	int err;
72 
73 	priv->ptp = kzalloc(sizeof(*priv->ptp), GFP_KERNEL);
74 	if (!priv->ptp)
75 		return -ENOMEM;
76 
77 	ptp = priv->ptp;
78 	ptp->info = gve_ptp_caps;
79 	ptp->clock = ptp_clock_register(&ptp->info, &priv->pdev->dev);
80 
81 	if (IS_ERR(ptp->clock)) {
82 		dev_err(&priv->pdev->dev, "PTP clock registration failed\n");
83 		err  = PTR_ERR(ptp->clock);
84 		goto free_ptp;
85 	}
86 
87 	ptp->priv = priv;
88 	return 0;
89 
90 free_ptp:
91 	kfree(ptp);
92 	priv->ptp = NULL;
93 	return err;
94 }
95 
96 static void gve_ptp_release(struct gve_priv *priv)
97 {
98 	struct gve_ptp *ptp = priv->ptp;
99 
100 	if (!ptp)
101 		return;
102 
103 	if (ptp->clock)
104 		ptp_clock_unregister(ptp->clock);
105 
106 	kfree(ptp);
107 	priv->ptp = NULL;
108 }
109 
110 int gve_init_clock(struct gve_priv *priv)
111 {
112 	int err;
113 
114 	err = gve_ptp_init(priv);
115 	if (err)
116 		return err;
117 
118 	priv->nic_ts_report =
119 		dma_alloc_coherent(&priv->pdev->dev,
120 				   sizeof(struct gve_nic_ts_report),
121 				   &priv->nic_ts_report_bus,
122 				   GFP_KERNEL);
123 	if (!priv->nic_ts_report) {
124 		dev_err(&priv->pdev->dev, "%s dma alloc error\n", __func__);
125 		err = -ENOMEM;
126 		goto release_ptp;
127 	}
128 	err = gve_clock_nic_ts_read(priv);
129 	if (err) {
130 		dev_err(&priv->pdev->dev, "failed to read NIC clock %d\n", err);
131 		goto release_nic_ts_report;
132 	}
133 	ptp_schedule_worker(priv->ptp->clock,
134 			    msecs_to_jiffies(GVE_NIC_TS_SYNC_INTERVAL_MS));
135 
136 	return 0;
137 
138 release_nic_ts_report:
139 	dma_free_coherent(&priv->pdev->dev,
140 			  sizeof(struct gve_nic_ts_report),
141 			  priv->nic_ts_report, priv->nic_ts_report_bus);
142 	priv->nic_ts_report = NULL;
143 release_ptp:
144 	gve_ptp_release(priv);
145 	return err;
146 }
147 
148 void gve_teardown_clock(struct gve_priv *priv)
149 {
150 	gve_ptp_release(priv);
151 
152 	if (priv->nic_ts_report) {
153 		dma_free_coherent(&priv->pdev->dev,
154 				  sizeof(struct gve_nic_ts_report),
155 				  priv->nic_ts_report, priv->nic_ts_report_bus);
156 		priv->nic_ts_report = NULL;
157 	}
158 }
159