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