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@bootlin.com>
---
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
On Mon, 26 Feb 2024 14:39:59 +0100 Kory Maincent wrote: > 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. Can we assume there's one PHC per netdev? We both store the netdev/phydev info in the ptp clock and ptp clock in the netdev. Is there a reason for that?
On Mon, Mar 04, 2024 at 06:57:34PM -0800, Jakub Kicinski wrote: > On Mon, 26 Feb 2024 14:39:59 +0100 Kory Maincent wrote: > > 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. > > Can we assume there's one PHC per netdev? > We both store the netdev/phydev info in the ptp clock > and ptp clock in the netdev. Is there a reason for that? No. In the case of mvpp2 + marvell PHY, the two PTP implementations are entirely separate. -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
On Tue, 5 Mar 2024 08:36:54 +0000 "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > On Mon, Mar 04, 2024 at 06:57:34PM -0800, Jakub Kicinski wrote: > > On Mon, 26 Feb 2024 14:39:59 +0100 Kory Maincent wrote: > > > 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. > > > > Can we assume there's one PHC per netdev? > > We both store the netdev/phydev info in the ptp clock > > and ptp clock in the netdev. Is there a reason for that? > > No. In the case of mvpp2 + marvell PHY, the two PTP implementations are > entirely separate. Yes the PTP clock can be independent from the netdev. We need to know which software layer register the PHC to be able to call its callbacks. My commit log is a bit small here. I will enhance it in the next version. Regards, -- Köry Maincent, Bootlin Embedded Linux and kernel engineering https://bootlin.com
On Tue, 5 Mar 2024 11:10:21 +0100 Köry Maincent wrote: > > No. In the case of mvpp2 + marvell PHY, the two PTP implementations are > > entirely separate. > > Yes the PTP clock can be independent from the netdev. > We need to know which software layer register the PHC to be able to call its > callbacks. > > My commit log is a bit small here. I will enhance it in the next version. Still, wouldn't it be simpler to store all accessible PTP instances in the netdev?
On Tue, 5 Mar 2024 06:59:39 -0800 Jakub Kicinski <kuba@kernel.org> wrote: > On Tue, 5 Mar 2024 11:10:21 +0100 Köry Maincent wrote: > > > No. In the case of mvpp2 + marvell PHY, the two PTP implementations are > > > entirely separate. > > > > Yes the PTP clock can be independent from the netdev. > > We need to know which software layer register the PHC to be able to call its > > callbacks. > > > > My commit log is a bit small here. I will enhance it in the next version. > > Still, wouldn't it be simpler to store all accessible PTP instances > in the netdev? You are talking about something like the phy topology but for the ptp? Then when asking information on a PHC (tsinfo or hwtstamp config) from ethtool we would have to look at the PHC topology of the netdev. This could work. Not sure it is much simpler, do you see other advantages that it could have? Regards, -- Köry Maincent, Bootlin Embedded Linux and kernel engineering https://bootlin.com
On Tue, 5 Mar 2024 16:35:46 +0100 Köry Maincent wrote: > > Still, wouldn't it be simpler to store all accessible PTP instances > > in the netdev? > > You are talking about something like the phy topology but for the ptp? > > Then when asking information on a PHC (tsinfo or hwtstamp config) from ethtool > we would have to look at the PHC topology of the netdev. This could work. Not > sure it is much simpler, do you see other advantages that it could have? I was thinking just an array indexed by enum hwtstamp_source. But you're right, once we can express more than one phy per netdev we're basically back to doing similar walks. Fair.
© 2016 - 2026 Red Hat, Inc.