File Index
Files and directories
Sign in
FILE

gve_ptp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/google/gve/gve_ptp.c C
  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. */
 14int 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
 29static 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
 36static int gve_ptp_settime64(struct ptp_clock_info *info,
 37			     const struct timespec64 *ts)
 38{
 39	return -EOPNOTSUPP;
 40}
 41
 42static 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
 56out:
 57	return msecs_to_jiffies(GVE_NIC_TS_SYNC_INTERVAL_MS);
 58}
 59
 60static 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
 68static 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
 90free_ptp:
 91	kfree(ptp);
 92	priv->ptp = NULL;
 93	return err;
 94}
 95
 96static 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
110int 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
138release_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;
143release_ptp:
144	gve_ptp_release(priv);
145	return err;
146}
147
148void 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}
~/ Read-only file preview.