[PATCH net-next v9 08/13] ptp: Add phc source and helpers to register specific PTP clock or get information

From: Kory Maincent
Date: Mon Feb 26 2024 - 08:42:24 EST


Prepare for future hardware timestamp selection by adding source and
corresponding pointers to ptp_clock structure. Additionally, introduce
helpers for registering specific phydev or netdev PTP clocks, retrieving
PTP clock information such as hwtstamp source or phydev/netdev pointers,
and obtaining the ptp_clock structure from the phc index.

Signed-off-by: Kory Maincent <kory.maincent@xxxxxxxxxxx>
---

Change in v8:
- New patch.
---
drivers/ptp/ptp_clock.c | 71 +++++++++++++++++++++++++++++++++
drivers/ptp/ptp_private.h | 5 +++
include/linux/ptp_clock_kernel.h | 84 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+)

diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index f374b1e89780..d7cd7e01990e 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -504,6 +504,77 @@ void ptp_cancel_worker_sync(struct ptp_clock *ptp)
}
EXPORT_SYMBOL(ptp_cancel_worker_sync);

+struct ptp_clock *netdev_ptp_clock_register(struct ptp_clock_info *info,
+ struct net_device *dev)
+{
+ struct ptp_clock *ptp;
+
+ ptp = ptp_clock_register(info, &dev->dev);
+ if (IS_ERR(ptp))
+ return ptp;
+
+ ptp->phc_source = HWTSTAMP_SOURCE_NETDEV;
+ ptp->netdev = dev;
+
+ return ptp;
+}
+EXPORT_SYMBOL(netdev_ptp_clock_register);
+
+struct ptp_clock *phydev_ptp_clock_register(struct ptp_clock_info *info,
+ struct phy_device *phydev)
+{
+ struct ptp_clock *ptp;
+
+ ptp = ptp_clock_register(info, &phydev->mdio.dev);
+ if (IS_ERR(ptp))
+ return ptp;
+
+ ptp->phc_source = HWTSTAMP_SOURCE_PHYLIB;
+ ptp->phydev = phydev;
+
+ return ptp;
+}
+EXPORT_SYMBOL(phydev_ptp_clock_register);
+
+bool ptp_clock_from_phylib(struct ptp_clock *ptp)
+{
+ return ptp->phc_source == HWTSTAMP_SOURCE_PHYLIB;
+}
+EXPORT_SYMBOL(ptp_clock_from_phylib);
+
+bool ptp_clock_from_netdev(struct ptp_clock *ptp)
+{
+ return ptp->phc_source == HWTSTAMP_SOURCE_NETDEV;
+}
+EXPORT_SYMBOL(ptp_clock_from_netdev);
+
+struct net_device *ptp_clock_netdev(struct ptp_clock *ptp)
+{
+ if (ptp->phc_source != HWTSTAMP_SOURCE_NETDEV)
+ return NULL;
+
+ return ptp->netdev;
+}
+EXPORT_SYMBOL(ptp_clock_netdev);
+
+struct phy_device *ptp_clock_phydev(struct ptp_clock *ptp)
+{
+ if (ptp->phc_source != HWTSTAMP_SOURCE_PHYLIB)
+ return NULL;
+
+ return ptp->phydev;
+}
+EXPORT_SYMBOL(ptp_clock_phydev);
+
+struct ptp_clock *ptp_clock_get_by_index(int index)
+{
+ if (index < 0)
+ return NULL;
+
+ return xa_load(&ptp_clocks_map, (unsigned long)index);
+}
+EXPORT_SYMBOL(ptp_clock_get_by_index);
+
/* module operations */

static void __exit ptp_exit(void)
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 45f9002a5dca..3faecc5b9136 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -41,6 +41,11 @@ struct ptp_clock {
struct ptp_clock_info *info;
dev_t devid;
int index; /* index into clocks.map */
+ enum hwtstamp_source phc_source;
+ union { /* Pointer of the phc_source device */
+ struct net_device *netdev;
+ struct phy_device *phydev;
+ };
struct pps_device *pps_source;
long dialed_frequency; /* remembers the frequency adjustment */
struct list_head tsevqs; /* timestamp fifo list */
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 6e4b8206c7d0..174a0b98632b 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -9,7 +9,9 @@
#define _PTP_CLOCK_KERNEL_H_

#include <linux/device.h>
+#include <linux/netdevice.h>
#include <linux/pps_kernel.h>
+#include <linux/phy.h>
#include <linux/ptp_clock.h>
#include <linux/timecounter.h>
#include <linux/skbuff.h>
@@ -340,6 +342,70 @@ extern void ptp_clock_event(struct ptp_clock *ptp,

extern int ptp_clock_index(struct ptp_clock *ptp);

+/**
+ * netdev_ptp_clock_register() - register a PTP hardware clock driver for
+ * a net device
+ *
+ * @info: Structure describing the new clock.
+ * @dev: Pointer of the net device
+ */
+
+extern struct ptp_clock *
+netdev_ptp_clock_register(struct ptp_clock_info *info,
+ struct net_device *dev);
+
+/**
+ * phydev_ptp_clock_register() - register a PTP hardware clock driver for
+ * a phy device
+ *
+ * @info: Structure describing the new clock.
+ * @phydev: Pointer of the phy device
+ */
+
+extern struct ptp_clock *
+phydev_ptp_clock_register(struct ptp_clock_info *info,
+ struct phy_device *phydev);
+
+/**
+ * ptp_clock_from_phylib() - return true if the PTP clock comes from phylib
+ *
+ * @ptp: The clock obtained from net/phy_ptp_clock_register().
+ */
+
+bool ptp_clock_from_phylib(struct ptp_clock *ptp);
+
+/**
+ * ptp_clock_from_netdev() - return true if the PTP clock comes from netdev
+ *
+ * @ptp: The clock obtained from net/phy_ptp_clock_register().
+ */
+
+bool ptp_clock_from_netdev(struct ptp_clock *ptp);
+
+/**
+ * ptp_clock_netdev() - obtain the net_device of PTP clock
+ *
+ * @ptp: The clock obtained from netdev_ptp_clock_register().
+ */
+
+struct net_device *ptp_clock_netdev(struct ptp_clock *ptp);
+
+/**
+ * ptp_clock_phydev() - obtain the phy_device of a PTP clock
+ *
+ * @ptp: The clock obtained from phydev_ptp_clock_register().
+ */
+
+struct phy_device *ptp_clock_phydev(struct ptp_clock *ptp);
+
+/**
+ * ptp_clock_get_by_index() - obtain the PTP clock from a given PHC index
+ *
+ * @index: The device index of a PTP clock.
+ */
+
+struct ptp_clock *ptp_clock_get_by_index(int index);
+
/**
* ptp_find_pin() - obtain the pin index of a given auxiliary function
*
@@ -405,6 +471,24 @@ static inline void ptp_clock_event(struct ptp_clock *ptp,
{ }
static inline int ptp_clock_index(struct ptp_clock *ptp)
{ return -1; }
+static inline struct ptp_clock *
+netdev_ptp_clock_register(struct ptp_clock_info *info,
+ struct net_device *dev)
+{ return NULL; }
+static inline struct ptp_clock *
+phydev_ptp_clock_register(struct ptp_clock_info *info,
+ struct phy_device *phydev)
+{ return NULL; }
+static inline bool ptp_clock_from_phylib(struct ptp_clock *ptp)
+{ return false; }
+static inline bool ptp_clock_from_netdev(struct ptp_clock *ptp)
+{ return false; }
+static inline struct net_device *ptp_clock_netdev(struct ptp_clock *ptp)
+{ return NULL; }
+static inline struct phy_device *ptp_clock_phydev(struct ptp_clock *ptp);
+{ return NULL; }
+static inline struct ptp_clock *ptp_clock_get_by_index(int index);
+{ return NULL; }
static inline int ptp_find_pin(struct ptp_clock *ptp,
enum ptp_pin_function func, unsigned int chan)
{ return -1; }

--
2.25.1