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. */
gve_clock_nic_ts_read(struct gve_priv * priv)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
gve_ptp_do_aux_work(struct ptp_clock_info * info)29 static long gve_ptp_do_aux_work(struct ptp_clock_info *info)
30 {
31 const struct gve_ptp *ptp = container_of(info, struct gve_ptp, info);
32 struct gve_priv *priv = ptp->priv;
33 int err;
34
35 if (gve_get_reset_in_progress(priv) || !gve_get_admin_queue_ok(priv))
36 goto out;
37
38 err = gve_clock_nic_ts_read(priv);
39 if (err && net_ratelimit())
40 dev_err(&priv->pdev->dev,
41 "%s read err %d\n", __func__, err);
42
43 out:
44 return msecs_to_jiffies(GVE_NIC_TS_SYNC_INTERVAL_MS);
45 }
46
47 static const struct ptp_clock_info gve_ptp_caps = {
48 .owner = THIS_MODULE,
49 .name = "gve clock",
50 .do_aux_work = gve_ptp_do_aux_work,
51 };
52
gve_ptp_init(struct gve_priv * priv)53 static int gve_ptp_init(struct gve_priv *priv)
54 {
55 struct gve_ptp *ptp;
56 int err;
57
58 if (!priv->nic_timestamp_supported) {
59 dev_dbg(&priv->pdev->dev, "Device does not support PTP\n");
60 return -EOPNOTSUPP;
61 }
62
63 priv->ptp = kzalloc(sizeof(*priv->ptp), GFP_KERNEL);
64 if (!priv->ptp)
65 return -ENOMEM;
66
67 ptp = priv->ptp;
68 ptp->info = gve_ptp_caps;
69 ptp->clock = ptp_clock_register(&ptp->info, &priv->pdev->dev);
70
71 if (IS_ERR(ptp->clock)) {
72 dev_err(&priv->pdev->dev, "PTP clock registration failed\n");
73 err = PTR_ERR(ptp->clock);
74 goto free_ptp;
75 }
76
77 ptp->priv = priv;
78 return 0;
79
80 free_ptp:
81 kfree(ptp);
82 priv->ptp = NULL;
83 return err;
84 }
85
gve_ptp_release(struct gve_priv * priv)86 static void gve_ptp_release(struct gve_priv *priv)
87 {
88 struct gve_ptp *ptp = priv->ptp;
89
90 if (!ptp)
91 return;
92
93 if (ptp->clock)
94 ptp_clock_unregister(ptp->clock);
95
96 kfree(ptp);
97 priv->ptp = NULL;
98 }
99
gve_init_clock(struct gve_priv * priv)100 int gve_init_clock(struct gve_priv *priv)
101 {
102 int err;
103
104 if (!priv->nic_timestamp_supported)
105 return 0;
106
107 err = gve_ptp_init(priv);
108 if (err)
109 return err;
110
111 priv->nic_ts_report =
112 dma_alloc_coherent(&priv->pdev->dev,
113 sizeof(struct gve_nic_ts_report),
114 &priv->nic_ts_report_bus,
115 GFP_KERNEL);
116 if (!priv->nic_ts_report) {
117 dev_err(&priv->pdev->dev, "%s dma alloc error\n", __func__);
118 err = -ENOMEM;
119 goto release_ptp;
120 }
121
122 return 0;
123
124 release_ptp:
125 gve_ptp_release(priv);
126 return err;
127 }
128
gve_teardown_clock(struct gve_priv * priv)129 void gve_teardown_clock(struct gve_priv *priv)
130 {
131 gve_ptp_release(priv);
132
133 if (priv->nic_ts_report) {
134 dma_free_coherent(&priv->pdev->dev,
135 sizeof(struct gve_nic_ts_report),
136 priv->nic_ts_report, priv->nic_ts_report_bus);
137 priv->nic_ts_report = NULL;
138 }
139 }
140