]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
gve: Add initial PTP device support
authorHarshitha Ramamurthy <hramamurthy@google.com>
Sat, 14 Jun 2025 00:07:49 +0000 (00:07 +0000)
committerJakub Kicinski <kuba@kernel.org>
Mon, 16 Jun 2025 22:27:24 +0000 (15:27 -0700)
If the device supports reading of the nic clock, add support
to initialize and register the PTP clock.

Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
Link: https://patch.msgid.link/20250614000754.164827-4-hramamurthy@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/google/Kconfig
drivers/net/ethernet/google/gve/Makefile
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_ptp.c [new file with mode: 0644]

index 564862a57124e2821ffe83b789c5d3656905101e..14c9431e15e5446af1ec12b0ef2302e2ee643773 100644 (file)
@@ -18,6 +18,7 @@ if NET_VENDOR_GOOGLE
 config GVE
        tristate "Google Virtual NIC (gVNIC) support"
        depends on (PCI_MSI && (X86 || CPU_LITTLE_ENDIAN))
+       depends on PTP_1588_CLOCK_OPTIONAL
        select PAGE_POOL
        help
          This driver supports Google Virtual NIC (gVNIC)"
index 4520f1c07a638fd97e3be483e6e41dc75de5f5fe..e0ec227a50f7e17d0ff97237c18d1acca940b99b 100644 (file)
@@ -1,5 +1,7 @@
 # Makefile for the Google virtual Ethernet (gve) driver
 
 obj-$(CONFIG_GVE) += gve.o
-gve-objs := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o gve_flow_rule.o \
+gve-y := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o gve_flow_rule.o \
            gve_buffer_mgmt_dqo.o
+
+gve-$(CONFIG_PTP_1588_CLOCK) += gve_ptp.o
index cf6947731a9b7d48d82481d05e44c4ee8748c395..8d2aa654fd4c4898579826dcd5cc9f3fc074f8da 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/ethtool_netlink.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/u64_stats_sync.h>
 #include <net/page_pool/helpers.h>
 #include <net/xdp.h>
@@ -750,6 +751,12 @@ struct gve_rss_config {
        u32 *hash_lut;
 };
 
+struct gve_ptp {
+       struct ptp_clock_info info;
+       struct ptp_clock *clock;
+       struct gve_priv *priv;
+};
+
 struct gve_priv {
        struct net_device *dev;
        struct gve_tx_ring *tx; /* array of tx_cfg.num_queues */
@@ -874,6 +881,7 @@ struct gve_priv {
 
        /* True if the device supports reading the nic clock */
        bool nic_timestamp_supported;
+       struct gve_ptp *ptp;
 };
 
 enum gve_service_task_flags_bit {
diff --git a/drivers/net/ethernet/google/gve/gve_ptp.c b/drivers/net/ethernet/google/gve/gve_ptp.c
new file mode 100644 (file)
index 0000000..293f8dd
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Google virtual Ethernet (gve) driver
+ *
+ * Copyright (C) 2025 Google LLC
+ */
+
+#include "gve.h"
+
+static const struct ptp_clock_info gve_ptp_caps = {
+       .owner          = THIS_MODULE,
+       .name           = "gve clock",
+};
+
+static int __maybe_unused gve_ptp_init(struct gve_priv *priv)
+{
+       struct gve_ptp *ptp;
+       int err;
+
+       if (!priv->nic_timestamp_supported) {
+               dev_dbg(&priv->pdev->dev, "Device does not support PTP\n");
+               return -EOPNOTSUPP;
+       }
+
+       priv->ptp = kzalloc(sizeof(*priv->ptp), GFP_KERNEL);
+       if (!priv->ptp)
+               return -ENOMEM;
+
+       ptp = priv->ptp;
+       ptp->info = gve_ptp_caps;
+       ptp->clock = ptp_clock_register(&ptp->info, &priv->pdev->dev);
+
+       if (IS_ERR(ptp->clock)) {
+               dev_err(&priv->pdev->dev, "PTP clock registration failed\n");
+               err  = PTR_ERR(ptp->clock);
+               goto free_ptp;
+       }
+
+       ptp->priv = priv;
+       return 0;
+
+free_ptp:
+       kfree(ptp);
+       priv->ptp = NULL;
+       return err;
+}
+
+static void __maybe_unused gve_ptp_release(struct gve_priv *priv)
+{
+       struct gve_ptp *ptp = priv->ptp;
+
+       if (!ptp)
+               return;
+
+       if (ptp->clock)
+               ptp_clock_unregister(ptp->clock);
+
+       kfree(ptp);
+       priv->ptp = NULL;
+}