linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set()
@ 2023-07-17 15:26 Vladimir Oltean
  2023-07-17 15:26 ` [PATCH v8 net-next 01/12] net: add NDOs for configuring hardware timestamping Vladimir Oltean
                   ` (12 more replies)
  0 siblings, 13 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:26 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

Based on previous RFCs from Maxim Georgiev:
https://lore.kernel.org/netdev/20230502043150.17097-1-glipus@gmail.com/

this series attempts to introduce new API for the hardware timestamping
control path (SIOCGHWTSTAMP and SIOCSHWTSTAMP handling).

I don't have any board with phylib hardware timestamping, so I would
appreciate testing (especially on lan966x, the most intricate
conversion). I was, however, able to test netdev level timestamping,
because I also have some more unsubmitted conversions in progress:

https://github.com/vladimiroltean/linux/commits/ndo-hwtstamp-v7

I hope that the concerns expressed in the comments of previous series
were addressed, and that Köry Maincent's series:
https://lore.kernel.org/netdev/20230406173308.401924-1-kory.maincent@bootlin.com/
can make progress in parallel with the conversion of the rest of drivers.

Maxim Georgiev (5):
  net: add NDOs for configuring hardware timestamping
  net: add hwtstamping helpers for stackable net devices
  net: vlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set()
  net: macvlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set()
  net: bonding: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set()

Vladimir Oltean (7):
  net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  net: fec: delete fec_ptp_disable_hwts()
  net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  net: lan966x: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  net: transfer rtnl_lock() requirement from
    ethtool_set_ethtool_phy_ops() to caller
  net: phy: provide phylib stubs for hardware timestamping operations
  net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from
    converted drivers

 drivers/net/bonding/bond_main.c               | 105 ++++++----
 drivers/net/ethernet/freescale/fec.h          |   6 +-
 drivers/net/ethernet/freescale/fec_main.c     |  56 +++---
 drivers/net/ethernet/freescale/fec_ptp.c      |  43 ++--
 .../ethernet/microchip/lan966x/lan966x_main.c |  58 +++---
 .../ethernet/microchip/lan966x/lan966x_main.h |  12 +-
 .../ethernet/microchip/lan966x/lan966x_ptp.c  |  34 ++--
 .../ethernet/microchip/sparx5/sparx5_main.h   |   9 +-
 .../ethernet/microchip/sparx5/sparx5_netdev.c |  35 ++--
 .../ethernet/microchip/sparx5/sparx5_ptp.c    |  24 ++-
 drivers/net/macvlan.c                         |  34 ++--
 drivers/net/phy/Makefile                      |   2 +
 drivers/net/phy/phy.c                         |  34 ++++
 drivers/net/phy/phy_device.c                  |  26 ++-
 include/linux/net_tstamp.h                    |  30 +++
 include/linux/netdevice.h                     |  25 +++
 include/linux/phy.h                           |   7 +
 net/8021q/vlan_dev.c                          |  27 ++-
 net/core/dev_ioctl.c                          | 184 +++++++++++++++++-
 net/ethtool/common.c                          |   3 +-
 20 files changed, 544 insertions(+), 210 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 01/12] net: add NDOs for configuring hardware timestamping
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
@ 2023-07-17 15:26 ` Vladimir Oltean
  2023-07-17 15:26 ` [PATCH v8 net-next 02/12] net: add hwtstamping helpers for stackable net devices Vladimir Oltean
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:26 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

From: Maxim Georgiev <glipus@gmail.com>

Current hardware timestamping API for NICs requires implementing
.ndo_eth_ioctl() for SIOCGHWTSTAMP and SIOCSHWTSTAMP.

That API has some boilerplate such as request parameter translation
between user and kernel address spaces, handling possible translation
failures correctly, etc. Since it is the same all across the board, it
would be desirable to handle it through generic code.

Here we introduce .ndo_hwtstamp_get() and .ndo_hwtstamp_set(), which
implement that boilerplate and allow drivers to just act upon requests.

Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Maxim Georgiev <glipus@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com>
---
Changes in v8:
- None
Changes in v7:
- Remove extack from ndo_hwtstamp_get()
- Reword commit message
Changes in v6:
- The patch title was updated. No code changes.
Changes in v4:
- Renamed hwtstamp_kernel_to_config() function to
  hwtstamp_config_from_kernel().
- Added struct kernel_hwtstamp_config zero initialization
  in dev_get_hwtstamp() and in dev_get_hwtstamp().
Changes in v3:
- Moved individual driver conversions to separate patches
Changes in v2:
- Introduced kernel_hwtstamp_config structure
- Added netlink_ext_ack* and kernel_hwtstamp_config* as NDO hw timestamp
  function parameters
- Reodered function variable declarations in dev_hwtstamp()
- Refactored error handling logic in dev_hwtstamp()
- Split dev_hwtstamp() into GET and SET versions
- Changed net_hwtstamp_validate() to accept struct hwtstamp_config *
  as a parameter

 include/linux/net_tstamp.h |  8 +++++++
 include/linux/netdevice.h  | 16 +++++++++++++
 net/core/dev_ioctl.c       | 46 ++++++++++++++++++++++++++++++++++++--
 3 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h
index fd67f3cc0c4b..7c59824f43f5 100644
--- a/include/linux/net_tstamp.h
+++ b/include/linux/net_tstamp.h
@@ -30,4 +30,12 @@ static inline void hwtstamp_config_to_kernel(struct kernel_hwtstamp_config *kern
 	kernel_cfg->rx_filter = cfg->rx_filter;
 }
 
+static inline void hwtstamp_config_from_kernel(struct hwtstamp_config *cfg,
+					       const struct kernel_hwtstamp_config *kernel_cfg)
+{
+	cfg->flags = kernel_cfg->flags;
+	cfg->tx_type = kernel_cfg->tx_type;
+	cfg->rx_filter = kernel_cfg->rx_filter;
+}
+
 #endif /* _LINUX_NET_TIMESTAMPING_H_ */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b828c7a75be2..17a442ed683b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -57,6 +57,7 @@
 struct netpoll_info;
 struct device;
 struct ethtool_ops;
+struct kernel_hwtstamp_config;
 struct phy_device;
 struct dsa_port;
 struct ip_tunnel_parm;
@@ -1418,6 +1419,16 @@ struct netdev_net_notifier {
  *	Get hardware timestamp based on normal/adjustable time or free running
  *	cycle counter. This function is required if physical clock supports a
  *	free running cycle counter.
+ *
+ * int (*ndo_hwtstamp_get)(struct net_device *dev,
+ *			   struct kernel_hwtstamp_config *kernel_config);
+ *	Get the currently configured hardware timestamping parameters for the
+ *	NIC device.
+ *
+ * int (*ndo_hwtstamp_set)(struct net_device *dev,
+ *			   struct kernel_hwtstamp_config *kernel_config,
+ *			   struct netlink_ext_ack *extack);
+ *	Change the hardware timestamping parameters for NIC device.
  */
 struct net_device_ops {
 	int			(*ndo_init)(struct net_device *dev);
@@ -1652,6 +1663,11 @@ struct net_device_ops {
 	ktime_t			(*ndo_get_tstamp)(struct net_device *dev,
 						  const struct skb_shared_hwtstamps *hwtstamps,
 						  bool cycles);
+	int			(*ndo_hwtstamp_get)(struct net_device *dev,
+						    struct kernel_hwtstamp_config *kernel_config);
+	int			(*ndo_hwtstamp_set)(struct net_device *dev,
+						    struct kernel_hwtstamp_config *kernel_config,
+						    struct netlink_ext_ack *extack);
 };
 
 struct xdp_metadata_ops {
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 3730945ee294..10c0e173b38b 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -254,11 +254,32 @@ static int dev_eth_ioctl(struct net_device *dev,
 
 static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 {
-	return dev_eth_ioctl(dev, ifr, SIOCGHWTSTAMP);
+	const struct net_device_ops *ops = dev->netdev_ops;
+	struct kernel_hwtstamp_config kernel_cfg = {};
+	struct hwtstamp_config cfg;
+	int err;
+
+	if (!ops->ndo_hwtstamp_get)
+		return dev_eth_ioctl(dev, ifr, SIOCGHWTSTAMP); /* legacy */
+
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	err = ops->ndo_hwtstamp_get(dev, &kernel_cfg);
+	if (err)
+		return err;
+
+	hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
+
+	if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
+		return -EFAULT;
+
+	return 0;
 }
 
 static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 {
+	const struct net_device_ops *ops = dev->netdev_ops;
 	struct kernel_hwtstamp_config kernel_cfg;
 	struct netlink_ext_ack extack = {};
 	struct hwtstamp_config cfg;
@@ -280,7 +301,28 @@ static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 		return err;
 	}
 
-	return dev_eth_ioctl(dev, ifr, SIOCSHWTSTAMP);
+	if (!ops->ndo_hwtstamp_set)
+		return dev_eth_ioctl(dev, ifr, SIOCSHWTSTAMP); /* legacy */
+
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	err = ops->ndo_hwtstamp_set(dev, &kernel_cfg, &extack);
+	if (err) {
+		if (extack._msg)
+			netdev_err(dev, "%s\n", extack._msg);
+		return err;
+	}
+
+	/* The driver may have modified the configuration, so copy the
+	 * updated version of it back to user space
+	 */
+	hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
+
+	if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
+		return -EFAULT;
+
+	return 0;
 }
 
 static int dev_siocbond(struct net_device *dev,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 02/12] net: add hwtstamping helpers for stackable net devices
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
  2023-07-17 15:26 ` [PATCH v8 net-next 01/12] net: add NDOs for configuring hardware timestamping Vladimir Oltean
@ 2023-07-17 15:26 ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 03/12] net: vlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() Vladimir Oltean
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:26 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

From: Maxim Georgiev <glipus@gmail.com>

The stackable net devices with hwtstamping support (vlan, macvlan,
bonding) only pass the hwtstamping ops to the lower (real) device.

These drivers are the first that need to be converted to the new
timestamping API, because if they aren't prepared to handle that,
then no real device driver cannot be converted to the new API either.

After studying what vlan_dev_ioctl(), macvlan_eth_ioctl() and
bond_eth_ioctl() have in common, here we propose two generic
implementations of ndo_hwtstamp_get() and ndo_hwtstamp_set() which
can be called by those 3 drivers, with "dev" being their lower device.

These helpers cover both cases, when the lower driver is converted to
the new API or unconverted.

We need some hacks in case of an unconverted driver, namely to stuff
some pointers in struct kernel_hwtstamp_config which shouldn't have
been there (since the new API isn't supposed to need it). These will
be removed when all drivers will have been converted to the new API.

Signed-off-by: Maxim Georgiev <glipus@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
---
Changes in v8:
- None
Changes in v7:
- Reword commit message
- Convert "int kernel_flags" to "bool copied_to_user"
- Minor style fixups, and a refactor of duplicated code into a common
  generic_hwtstamp_ioctl_lower()
Changes in v6:
- Patch title was updated. No code changes.
Changes in v5:
- kernel_hwtstamp_config kdoc is updated with the new field
  descriptions.
Changes in V4:
- Introducing KERNEL_HWTSTAMP_FLAG_IFR_RESULT flag indicating that
  the operation results are returned in the ifr referred by
  struct kernel_hwtstamp_config instead of kernel_hwtstamp_config
  glags/tx_type/rx_filter fields.
- Implementing generic_hwtstamp_set/set_lower() functions
  which will be used by vlan, maxvlan, bond and potentially
  other drivers translating ndo_hwtstamp_set/set calls to
  lower level drivers.

 include/linux/net_tstamp.h |  6 +++
 include/linux/netdevice.h  |  5 +++
 net/core/dev_ioctl.c       | 75 ++++++++++++++++++++++++++++++++++----
 3 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h
index 7c59824f43f5..03e922814851 100644
--- a/include/linux/net_tstamp.h
+++ b/include/linux/net_tstamp.h
@@ -11,6 +11,10 @@
  * @flags: see struct hwtstamp_config
  * @tx_type: see struct hwtstamp_config
  * @rx_filter: see struct hwtstamp_config
+ * @ifr: pointer to ifreq structure from the original ioctl request, to pass to
+ *	a legacy implementation of a lower driver
+ * @copied_to_user: request was passed to a legacy implementation which already
+ *	copied the ioctl request back to user space
  *
  * Prefer using this structure for in-kernel processing of hardware
  * timestamping configuration, over the inextensible struct hwtstamp_config
@@ -20,6 +24,8 @@ struct kernel_hwtstamp_config {
 	int flags;
 	int tx_type;
 	int rx_filter;
+	struct ifreq *ifr;
+	bool copied_to_user;
 };
 
 static inline void hwtstamp_config_to_kernel(struct kernel_hwtstamp_config *kernel_cfg,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 17a442ed683b..ca3bcf2257c0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3949,6 +3949,11 @@ int put_user_ifreq(struct ifreq *ifr, void __user *arg);
 int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
 		void __user *data, bool *need_copyout);
 int dev_ifconf(struct net *net, struct ifconf __user *ifc);
+int generic_hwtstamp_get_lower(struct net_device *dev,
+			       struct kernel_hwtstamp_config *kernel_cfg);
+int generic_hwtstamp_set_lower(struct net_device *dev,
+			       struct kernel_hwtstamp_config *kernel_cfg,
+			       struct netlink_ext_ack *extack);
 int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *userdata);
 unsigned int dev_get_flags(const struct net_device *);
 int __dev_change_flags(struct net_device *dev, unsigned int flags,
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 10c0e173b38b..d0223ecd6f6f 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -265,14 +265,20 @@ static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 	if (!netif_device_present(dev))
 		return -ENODEV;
 
+	kernel_cfg.ifr = ifr;
 	err = ops->ndo_hwtstamp_get(dev, &kernel_cfg);
 	if (err)
 		return err;
 
-	hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
+	/* If the request was resolved through an unconverted driver, omit
+	 * the copy_to_user(), since the implementation has already done that
+	 */
+	if (!kernel_cfg.copied_to_user) {
+		hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
 
-	if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
-		return -EFAULT;
+		if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
+			return -EFAULT;
+	}
 
 	return 0;
 }
@@ -280,7 +286,7 @@ static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
-	struct kernel_hwtstamp_config kernel_cfg;
+	struct kernel_hwtstamp_config kernel_cfg = {};
 	struct netlink_ext_ack extack = {};
 	struct hwtstamp_config cfg;
 	int err;
@@ -289,6 +295,7 @@ static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 		return -EFAULT;
 
 	hwtstamp_config_to_kernel(&kernel_cfg, &cfg);
+	kernel_cfg.ifr = ifr;
 
 	err = net_hwtstamp_validate(&kernel_cfg);
 	if (err)
@@ -317,14 +324,68 @@ static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 	/* The driver may have modified the configuration, so copy the
 	 * updated version of it back to user space
 	 */
-	hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
+	if (!kernel_cfg.copied_to_user) {
+		hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
 
-	if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
-		return -EFAULT;
+		if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int generic_hwtstamp_ioctl_lower(struct net_device *dev, int cmd,
+					struct kernel_hwtstamp_config *kernel_cfg)
+{
+	struct ifreq ifrr;
+	int err;
+
+	strscpy_pad(ifrr.ifr_name, dev->name, IFNAMSIZ);
+	ifrr.ifr_ifru = kernel_cfg->ifr->ifr_ifru;
+
+	err = dev_eth_ioctl(dev, &ifrr, cmd);
+	if (err)
+		return err;
+
+	kernel_cfg->ifr->ifr_ifru = ifrr.ifr_ifru;
+	kernel_cfg->copied_to_user = true;
 
 	return 0;
 }
 
+int generic_hwtstamp_get_lower(struct net_device *dev,
+			       struct kernel_hwtstamp_config *kernel_cfg)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	if (ops->ndo_hwtstamp_get)
+		return ops->ndo_hwtstamp_get(dev, kernel_cfg);
+
+	/* Legacy path: unconverted lower driver */
+	return generic_hwtstamp_ioctl_lower(dev, SIOCGHWTSTAMP, kernel_cfg);
+}
+EXPORT_SYMBOL(generic_hwtstamp_get_lower);
+
+int generic_hwtstamp_set_lower(struct net_device *dev,
+			       struct kernel_hwtstamp_config *kernel_cfg,
+			       struct netlink_ext_ack *extack)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	if (ops->ndo_hwtstamp_set)
+		return ops->ndo_hwtstamp_set(dev, kernel_cfg, extack);
+
+	/* Legacy path: unconverted lower driver */
+	return generic_hwtstamp_ioctl_lower(dev, SIOCSHWTSTAMP, kernel_cfg);
+}
+EXPORT_SYMBOL(generic_hwtstamp_set_lower);
+
 static int dev_siocbond(struct net_device *dev,
 			struct ifreq *ifr, unsigned int cmd)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 03/12] net: vlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
  2023-07-17 15:26 ` [PATCH v8 net-next 01/12] net: add NDOs for configuring hardware timestamping Vladimir Oltean
  2023-07-17 15:26 ` [PATCH v8 net-next 02/12] net: add hwtstamping helpers for stackable net devices Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 04/12] net: macvlan: " Vladimir Oltean
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

From: Maxim Georgiev <glipus@gmail.com>

8021q is one of the stackable net devices which pass the hardware
timestamping ops to the real device through ndo_eth_ioctl(). This
prevents converting any device driver to the new hwtimestamping API
without regressions.

Remove that limitation in the vlan driver by using the newly introduced
helpers for timestamping through lower devices, that handle both the new
and the old driver API.

Signed-off-by: Maxim Georgiev <glipus@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
---
Changes in v8:
- None.
Changes in v7:
- Split vlan and macvlan to separate patches
- Reword commit message
Changes in v6:
- Patch title was updated. No code changes.
Changes in v5:
- Re-introduced the net namespace check which
  was dropped in v4.
Changes in v4:
- Moved hw timestamp get/set request processing logic
  from vlan_dev_ioctl() to .ndo_hwtstamp_get/set callbacks.
- Use the shared generic_hwtstamp_get/set_lower() functions
  to handle ndo_hwtstamp_get/set requests.
- Apply the same changes to macvlan driver.

 net/8021q/vlan_dev.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index b90781b9ece6..2a7f1b15714a 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -354,6 +354,26 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p)
 	return 0;
 }
 
+static int vlan_hwtstamp_get(struct net_device *dev,
+			     struct kernel_hwtstamp_config *cfg)
+{
+	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
+
+	return generic_hwtstamp_get_lower(real_dev, cfg);
+}
+
+static int vlan_hwtstamp_set(struct net_device *dev,
+			     struct kernel_hwtstamp_config *cfg,
+			     struct netlink_ext_ack *extack)
+{
+	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
+
+	if (!net_eq(dev_net(dev), dev_net(real_dev)))
+		return -EOPNOTSUPP;
+
+	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
+}
+
 static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
@@ -365,14 +385,9 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	ifrr.ifr_ifru = ifr->ifr_ifru;
 
 	switch (cmd) {
-	case SIOCSHWTSTAMP:
-		if (!net_eq(dev_net(dev), dev_net(real_dev)))
-			break;
-		fallthrough;
 	case SIOCGMIIPHY:
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
-	case SIOCGHWTSTAMP:
 		if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
 			err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
 		break;
@@ -1081,6 +1096,8 @@ static const struct net_device_ops vlan_netdev_ops = {
 	.ndo_fix_features	= vlan_dev_fix_features,
 	.ndo_get_iflink		= vlan_dev_get_iflink,
 	.ndo_fill_forward_path	= vlan_dev_fill_forward_path,
+	.ndo_hwtstamp_get	= vlan_hwtstamp_get,
+	.ndo_hwtstamp_set	= vlan_hwtstamp_set,
 };
 
 static void vlan_dev_free(struct net_device *dev)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 04/12] net: macvlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (2 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 03/12] net: vlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 05/12] net: bonding: " Vladimir Oltean
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

From: Maxim Georgiev <glipus@gmail.com>

macvlan is one of the stackable net devices which pass the hardware
timestamping ops to the real device through ndo_eth_ioctl(). This
prevents converting any device driver to the new hwtimestamping API
without regressions.

Remove that limitation in macvlan by using the newly introduced helpers
for timestamping through lower devices, that handle both the new and the
old driver API.

macvlan only implements ndo_eth_ioctl() for these 2 operations, so
delete that method.

Signed-off-by: Maxim Georgiev <glipus@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
---
Changes in v8:
- None.
Changes in v7:
- Split vlan and macvlan to separate patches
- Reword commit message
Changes in v6:
- Patch title was updated. No code changes.
Changes in v5:
- Re-introduced the net namespace check which
  was dropped in v4.
Changes in v4:
- Moved hw timestamp get/set request processing logic
  from vlan_dev_ioctl() to .ndo_hwtstamp_get/set callbacks.
- Use the shared generic_hwtstamp_get/set_lower() functions
  to handle ndo_hwtstamp_get/set requests.
- Apply the same changes to macvlan driver.

 drivers/net/macvlan.c | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 4a53debf9d7c..01acb57aa40c 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -868,31 +868,24 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
-static int macvlan_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int macvlan_hwtstamp_get(struct net_device *dev,
+				struct kernel_hwtstamp_config *cfg)
 {
 	struct net_device *real_dev = macvlan_dev_real_dev(dev);
-	const struct net_device_ops *ops = real_dev->netdev_ops;
-	struct ifreq ifrr;
-	int err = -EOPNOTSUPP;
 
-	strscpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ);
-	ifrr.ifr_ifru = ifr->ifr_ifru;
+	return generic_hwtstamp_get_lower(real_dev, cfg);
+}
 
-	switch (cmd) {
-	case SIOCSHWTSTAMP:
-		if (!net_eq(dev_net(dev), &init_net))
-			break;
-		fallthrough;
-	case SIOCGHWTSTAMP:
-		if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
-			err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
-		break;
-	}
+static int macvlan_hwtstamp_set(struct net_device *dev,
+				struct kernel_hwtstamp_config *cfg,
+				struct netlink_ext_ack *extack)
+{
+	struct net_device *real_dev = macvlan_dev_real_dev(dev);
 
-	if (!err)
-		ifr->ifr_ifru = ifrr.ifr_ifru;
+	if (!net_eq(dev_net(dev), &init_net))
+		return -EOPNOTSUPP;
 
-	return err;
+	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
 }
 
 /*
@@ -1193,7 +1186,6 @@ static const struct net_device_ops macvlan_netdev_ops = {
 	.ndo_stop		= macvlan_stop,
 	.ndo_start_xmit		= macvlan_start_xmit,
 	.ndo_change_mtu		= macvlan_change_mtu,
-	.ndo_eth_ioctl		= macvlan_eth_ioctl,
 	.ndo_fix_features	= macvlan_fix_features,
 	.ndo_change_rx_flags	= macvlan_change_rx_flags,
 	.ndo_set_mac_address	= macvlan_set_mac_address,
@@ -1212,6 +1204,8 @@ static const struct net_device_ops macvlan_netdev_ops = {
 #endif
 	.ndo_get_iflink		= macvlan_dev_get_iflink,
 	.ndo_features_check	= passthru_features_check,
+	.ndo_hwtstamp_get	= macvlan_hwtstamp_get,
+	.ndo_hwtstamp_set	= macvlan_hwtstamp_set,
 };
 
 static void macvlan_dev_free(struct net_device *dev)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 05/12] net: bonding: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (3 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 04/12] net: macvlan: " Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

From: Maxim Georgiev <glipus@gmail.com>

bonding is one of the stackable net devices which pass the hardware
timestamping ops to the real device through ndo_eth_ioctl(). This
prevents converting any device driver to the new hwtimestamping API
without regressions.

Remove that limitation in bonding by using the newly introduced helpers
for timestamping through lower devices, that handle both the new and the
old driver API.

Signed-off-by: Maxim Georgiev <glipus@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
---
Changes in v8:
- None.
Changes in v7:
- Use copied_to_user instead of KERNEL_HWTSTAMP_FLAG_IFR_RESULT
- Reword commit message
Changes in v6:
- Patch title was updated. No code changes.

 drivers/net/bonding/bond_main.c | 105 ++++++++++++++++++++------------
 1 file changed, 65 insertions(+), 40 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 7a0f25301f7e..d591992e3eda 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4441,11 +4441,6 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct mii_ioctl_data *mii = NULL;
-	const struct net_device_ops *ops;
-	struct net_device *real_dev;
-	struct hwtstamp_config cfg;
-	struct ifreq ifrr;
-	int res = 0;
 
 	netdev_dbg(bond_dev, "bond_eth_ioctl: cmd=%d\n", cmd);
 
@@ -4472,44 +4467,11 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm
 		}
 
 		break;
-	case SIOCSHWTSTAMP:
-		if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
-			return -EFAULT;
-
-		if (!(cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX))
-			return -EOPNOTSUPP;
-
-		fallthrough;
-	case SIOCGHWTSTAMP:
-		real_dev = bond_option_active_slave_get_rcu(bond);
-		if (!real_dev)
-			return -EOPNOTSUPP;
-
-		strscpy_pad(ifrr.ifr_name, real_dev->name, IFNAMSIZ);
-		ifrr.ifr_ifru = ifr->ifr_ifru;
-
-		ops = real_dev->netdev_ops;
-		if (netif_device_present(real_dev) && ops->ndo_eth_ioctl) {
-			res = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
-			if (res)
-				return res;
-
-			ifr->ifr_ifru = ifrr.ifr_ifru;
-			if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
-				return -EFAULT;
-
-			/* Set the BOND_PHC_INDEX flag to notify user space */
-			cfg.flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX;
-
-			return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ?
-				-EFAULT : 0;
-		}
-		fallthrough;
 	default:
-		res = -EOPNOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
-	return res;
+	return 0;
 }
 
 static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
@@ -5683,6 +5645,67 @@ static u32 bond_mode_bcast_speed(struct slave *slave, u32 speed)
 	return speed;
 }
 
+/* Set the BOND_PHC_INDEX flag to notify user space */
+static int bond_set_phc_index_flag(struct kernel_hwtstamp_config *kernel_cfg)
+{
+	struct ifreq *ifr = kernel_cfg->ifr;
+	struct hwtstamp_config cfg;
+
+	if (kernel_cfg->copied_to_user) {
+		/* Lower device has a legacy implementation */
+		if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+			return -EFAULT;
+
+		cfg.flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX;
+		if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
+			return -EFAULT;
+	} else {
+		kernel_cfg->flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX;
+	}
+
+	return 0;
+}
+
+static int bond_hwtstamp_get(struct net_device *dev,
+			     struct kernel_hwtstamp_config *cfg)
+{
+	struct bonding *bond = netdev_priv(dev);
+	struct net_device *real_dev;
+	int err;
+
+	real_dev = bond_option_active_slave_get_rcu(bond);
+	if (!real_dev)
+		return -EOPNOTSUPP;
+
+	err = generic_hwtstamp_get_lower(real_dev, cfg);
+	if (err)
+		return err;
+
+	return bond_set_phc_index_flag(cfg);
+}
+
+static int bond_hwtstamp_set(struct net_device *dev,
+			     struct kernel_hwtstamp_config *cfg,
+			     struct netlink_ext_ack *extack)
+{
+	struct bonding *bond = netdev_priv(dev);
+	struct net_device *real_dev;
+	int err;
+
+	if (!(cfg->flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX))
+		return -EOPNOTSUPP;
+
+	real_dev = bond_option_active_slave_get_rcu(bond);
+	if (!real_dev)
+		return -EOPNOTSUPP;
+
+	err = generic_hwtstamp_set_lower(real_dev, cfg, extack);
+	if (err)
+		return err;
+
+	return bond_set_phc_index_flag(cfg);
+}
+
 static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
 					   struct ethtool_link_ksettings *cmd)
 {
@@ -5831,6 +5854,8 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_bpf		= bond_xdp,
 	.ndo_xdp_xmit           = bond_xdp_xmit,
 	.ndo_xdp_get_xmit_slave = bond_xdp_get_xmit_slave,
+	.ndo_hwtstamp_get	= bond_hwtstamp_get,
+	.ndo_hwtstamp_set	= bond_hwtstamp_set,
 };
 
 static const struct device_type bond_type = {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (4 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 05/12] net: bonding: " Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-18 14:20   ` Russell King (Oracle)
  2023-07-17 15:27 ` [PATCH v8 net-next 07/12] net: fec: delete fec_ptp_disable_hwts() Vladimir Oltean
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

The hardware timestamping through ndo_eth_ioctl() is going away.
Convert the FEC driver to the new API before that can be removed.

After removing the timestamping logic from fec_enet_ioctl(), the rest
is equivalent to phy_do_ioctl_running().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Wei Fang <wei.fang@nxp.com>
---
Changes in v8:
- Use phy_do_ioctl_running()
Changes in v7:
- Patch is new

 drivers/net/ethernet/freescale/fec.h      |  5 +-
 drivers/net/ethernet/freescale/fec_main.c | 67 +++++++++++++----------
 drivers/net/ethernet/freescale/fec_ptp.c  | 31 ++++-------
 3 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 63a053dea819..5d7b76f0c829 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -704,8 +704,9 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx);
 void fec_ptp_stop(struct platform_device *pdev);
 void fec_ptp_start_cyclecounter(struct net_device *ndev);
 void fec_ptp_disable_hwts(struct net_device *ndev);
-int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
-int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
+int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config,
+		struct netlink_ext_ack *extack);
+void fec_ptp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config);
 
 /****************************************************************************/
 #endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1b990a486059..c35b569d848a 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3237,33 +3237,6 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
 	.self_test		= net_selftest,
 };
 
-static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phydev = ndev->phydev;
-
-	if (!netif_running(ndev))
-		return -EINVAL;
-
-	if (!phydev)
-		return -ENODEV;
-
-	if (fep->bufdesc_ex) {
-		bool use_fec_hwts = !phy_has_hwtstamp(phydev);
-
-		if (cmd == SIOCSHWTSTAMP) {
-			if (use_fec_hwts)
-				return fec_ptp_set(ndev, rq);
-			fec_ptp_disable_hwts(ndev);
-		} else if (cmd == SIOCGHWTSTAMP) {
-			if (use_fec_hwts)
-				return fec_ptp_get(ndev, rq);
-		}
-	}
-
-	return phy_mii_ioctl(phydev, rq, cmd);
-}
-
 static void fec_enet_free_buffers(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
@@ -3927,6 +3900,42 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
 	return sent_frames;
 }
 
+static int fec_hwtstamp_get(struct net_device *ndev,
+			    struct kernel_hwtstamp_config *config)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phydev = ndev->phydev;
+
+	if (phy_has_hwtstamp(phydev))
+		return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
+
+	if (!fep->bufdesc_ex)
+		return -EOPNOTSUPP;
+
+	fec_ptp_get(ndev, config);
+
+	return 0;
+}
+
+static int fec_hwtstamp_set(struct net_device *ndev,
+			    struct kernel_hwtstamp_config *config,
+			    struct netlink_ext_ack *extack)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phydev = ndev->phydev;
+
+	if (phy_has_hwtstamp(phydev)) {
+		fec_ptp_disable_hwts(ndev);
+
+		return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
+	}
+
+	if (!fep->bufdesc_ex)
+		return -EOPNOTSUPP;
+
+	return fec_ptp_set(ndev, config, extack);
+}
+
 static const struct net_device_ops fec_netdev_ops = {
 	.ndo_open		= fec_enet_open,
 	.ndo_stop		= fec_enet_close,
@@ -3936,13 +3945,15 @@ static const struct net_device_ops fec_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= fec_timeout,
 	.ndo_set_mac_address	= fec_set_mac_address,
-	.ndo_eth_ioctl		= fec_enet_ioctl,
+	.ndo_eth_ioctl		= phy_do_ioctl_running,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= fec_poll_controller,
 #endif
 	.ndo_set_features	= fec_set_features,
 	.ndo_bpf		= fec_enet_bpf,
 	.ndo_xdp_xmit		= fec_enet_xdp_xmit,
+	.ndo_hwtstamp_get	= fec_hwtstamp_get,
+	.ndo_hwtstamp_set	= fec_hwtstamp_set,
 };
 
 static const unsigned short offset_des_active_rxq[] = {
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index afc658d2c271..50943db40f2d 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -618,16 +618,12 @@ void fec_ptp_disable_hwts(struct net_device *ndev)
 	fep->hwts_rx_en = 0;
 }
 
-int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)
+int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config,
+		struct netlink_ext_ack *extack)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	struct hwtstamp_config config;
-
-	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
-		return -EFAULT;
-
-	switch (config.tx_type) {
+	switch (config->tx_type) {
 	case HWTSTAMP_TX_OFF:
 		fep->hwts_tx_en = 0;
 		break;
@@ -638,33 +634,28 @@ int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)
 		return -ERANGE;
 	}
 
-	switch (config.rx_filter) {
+	switch (config->rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		fep->hwts_rx_en = 0;
 		break;
 
 	default:
 		fep->hwts_rx_en = 1;
-		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		config->rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
 	}
 
-	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-	    -EFAULT : 0;
+	return 0;
 }
 
-int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr)
+void fec_ptp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct hwtstamp_config config;
-
-	config.flags = 0;
-	config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
-	config.rx_filter = (fep->hwts_rx_en ?
-			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
 
-	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-		-EFAULT : 0;
+	config->flags = 0;
+	config->tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+	config->rx_filter = (fep->hwts_rx_en ?
+			     HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
 }
 
 /*
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 07/12] net: fec: delete fec_ptp_disable_hwts()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (5 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

Commit 340746398b67 ("net: fec: fix hardware time stamping by external
devices") was overly cautious with calling fec_ptp_disable_hwts() when
cmd == SIOCSHWTSTAMP and use_fec_hwts == false, because use_fec_hwts is
based on a runtime invariant (phy_has_hwtstamp()). Thus, if use_fec_hwts
is false, then fep->hwts_tx_en and fep->hwts_rx_en cannot be changed at
runtime; their values depend on the initial memory allocation, which
already sets them to zeroes.

If the core will ever gain support for switching timestamping layers,
it will arrange for a more organized calling convention and disable
timestamping in the previous layer as a first step. This means that the
code in the FEC driver is not necessary in any case.

The purpose of this change is to arrange the phy_has_hwtstamp() code in
a way in which it can be refactored away into generic logic.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Wei Fang <wei.fang@nxp.com>
---
Changes in v8:
- None
Changes in v7:
- Patch is new

 drivers/net/ethernet/freescale/fec.h      |  1 -
 drivers/net/ethernet/freescale/fec_main.c |  5 +----
 drivers/net/ethernet/freescale/fec_ptp.c  | 12 ------------
 3 files changed, 1 insertion(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5d7b76f0c829..ae356c5c2ba1 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -703,7 +703,6 @@ struct fec_enet_private {
 void fec_ptp_init(struct platform_device *pdev, int irq_idx);
 void fec_ptp_stop(struct platform_device *pdev);
 void fec_ptp_start_cyclecounter(struct net_device *ndev);
-void fec_ptp_disable_hwts(struct net_device *ndev);
 int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config,
 		struct netlink_ext_ack *extack);
 void fec_ptp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config);
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index c35b569d848a..28c5f8f8106d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3924,11 +3924,8 @@ static int fec_hwtstamp_set(struct net_device *ndev,
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = ndev->phydev;
 
-	if (phy_has_hwtstamp(phydev)) {
-		fec_ptp_disable_hwts(ndev);
-
+	if (phy_has_hwtstamp(phydev))
 		return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
-	}
 
 	if (!fep->bufdesc_ex)
 		return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 50943db40f2d..8e64399452ef 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -606,18 +606,6 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
 	}
 }
 
-/**
- * fec_ptp_disable_hwts - disable hardware time stamping
- * @ndev: pointer to net_device
- */
-void fec_ptp_disable_hwts(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	fep->hwts_tx_en = 0;
-	fep->hwts_rx_en = 0;
-}
-
 int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config,
 		struct netlink_ext_ack *extack)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (6 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 07/12] net: fec: delete fec_ptp_disable_hwts() Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-18 14:06   ` Steen Hegelund
  2023-07-17 15:27 ` [PATCH v8 net-next 09/12] net: lan966x: " Vladimir Oltean
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

The hardware timestamping through ndo_eth_ioctl() is going away.
Convert the sparx5 driver to the new API before that can be removed.

After removing the timestamping logic from sparx5_port_ioctl(), the rest
is equivalent to phy_do_ioctl().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
---
Changes in v8:
- Use phy_do_ioctl()
Changes in v7:
- Patch is new

 .../ethernet/microchip/sparx5/sparx5_main.h   |  9 ++--
 .../ethernet/microchip/sparx5/sparx5_netdev.c | 41 +++++++++++++------
 .../ethernet/microchip/sparx5/sparx5_ptp.c    | 24 +++++------
 3 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
index 62c85463b634..89a9a7afa32c 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
@@ -205,7 +205,7 @@ enum sparx5_core_clockfreq {
 struct sparx5_phc {
 	struct ptp_clock *clock;
 	struct ptp_clock_info info;
-	struct hwtstamp_config hwtstamp_config;
+	struct kernel_hwtstamp_config hwtstamp_config;
 	struct sparx5 *sparx5;
 	u8 index;
 };
@@ -388,8 +388,11 @@ void sparx5_unregister_netdevs(struct sparx5 *sparx5);
 /* sparx5_ptp.c */
 int sparx5_ptp_init(struct sparx5 *sparx5);
 void sparx5_ptp_deinit(struct sparx5 *sparx5);
-int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr);
-int sparx5_ptp_hwtstamp_get(struct sparx5_port *port, struct ifreq *ifr);
+int sparx5_ptp_hwtstamp_set(struct sparx5_port *port,
+			    struct kernel_hwtstamp_config *cfg,
+			    struct netlink_ext_ack *extack);
+void sparx5_ptp_hwtstamp_get(struct sparx5_port *port,
+			     struct kernel_hwtstamp_config *cfg);
 void sparx5_ptp_rxtstamp(struct sparx5 *sparx5, struct sk_buff *skb,
 			 u64 timestamp);
 int sparx5_ptp_txtstamp_request(struct sparx5_port *port,
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
index d078156581d5..e01d3b1e17e0 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
@@ -210,22 +210,37 @@ static int sparx5_get_port_parent_id(struct net_device *dev,
 	return 0;
 }
 
-static int sparx5_port_ioctl(struct net_device *dev, struct ifreq *ifr,
-			     int cmd)
+static int sparx5_port_hwtstamp_get(struct net_device *dev,
+				    struct kernel_hwtstamp_config *cfg)
 {
 	struct sparx5_port *sparx5_port = netdev_priv(dev);
 	struct sparx5 *sparx5 = sparx5_port->sparx5;
 
-	if (!phy_has_hwtstamp(dev->phydev) && sparx5->ptp) {
-		switch (cmd) {
-		case SIOCSHWTSTAMP:
-			return sparx5_ptp_hwtstamp_set(sparx5_port, ifr);
-		case SIOCGHWTSTAMP:
-			return sparx5_ptp_hwtstamp_get(sparx5_port, ifr);
-		}
-	}
+	if (phy_has_hwtstamp(dev->phydev))
+		return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP);
+
+	if (!sparx5->ptp)
+		return -EOPNOTSUPP;
+
+	sparx5_ptp_hwtstamp_get(sparx5_port, cfg);
+
+	return 0;
+}
+
+static int sparx5_port_hwtstamp_set(struct net_device *dev,
+				    struct kernel_hwtstamp_config *cfg,
+				    struct netlink_ext_ack *extack)
+{
+	struct sparx5_port *sparx5_port = netdev_priv(dev);
+	struct sparx5 *sparx5 = sparx5_port->sparx5;
+
+	if (phy_has_hwtstamp(dev->phydev))
+		return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP);
+
+	if (!sparx5->ptp)
+		return -EOPNOTSUPP;
 
-	return phy_mii_ioctl(dev->phydev, ifr, cmd);
+	return sparx5_ptp_hwtstamp_set(sparx5_port, cfg, extack);
 }
 
 static const struct net_device_ops sparx5_port_netdev_ops = {
@@ -238,8 +253,10 @@ static const struct net_device_ops sparx5_port_netdev_ops = {
 	.ndo_validate_addr      = eth_validate_addr,
 	.ndo_get_stats64        = sparx5_get_stats64,
 	.ndo_get_port_parent_id = sparx5_get_port_parent_id,
-	.ndo_eth_ioctl          = sparx5_port_ioctl,
+	.ndo_eth_ioctl          = phy_do_ioctl,
 	.ndo_setup_tc           = sparx5_port_setup_tc,
+	.ndo_hwtstamp_get       = sparx5_port_hwtstamp_get,
+	.ndo_hwtstamp_set       = sparx5_port_hwtstamp_set,
 };
 
 bool sparx5_netdevice_check(const struct net_device *dev)
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
index 0edb98cef7e4..5a932460db58 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
@@ -74,10 +74,11 @@ static u64 sparx5_ptp_get_nominal_value(struct sparx5 *sparx5)
 	return res;
 }
 
-int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr)
+int sparx5_ptp_hwtstamp_set(struct sparx5_port *port,
+			    struct kernel_hwtstamp_config *cfg,
+			    struct netlink_ext_ack *extack)
 {
 	struct sparx5 *sparx5 = port->sparx5;
-	struct hwtstamp_config cfg;
 	struct sparx5_phc *phc;
 
 	/* For now don't allow to run ptp on ports that are part of a bridge,
@@ -88,10 +89,7 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr)
 	if (test_bit(port->portno, sparx5->bridge_mask))
 		return -EINVAL;
 
-	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
-		return -EFAULT;
-
-	switch (cfg.tx_type) {
+	switch (cfg->tx_type) {
 	case HWTSTAMP_TX_ON:
 		port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
 		break;
@@ -105,7 +103,7 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr)
 		return -ERANGE;
 	}
 
-	switch (cfg.rx_filter) {
+	switch (cfg->rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		break;
 	case HWTSTAMP_FILTER_ALL:
@@ -122,7 +120,7 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr)
 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 	case HWTSTAMP_FILTER_NTP_ALL:
-		cfg.rx_filter = HWTSTAMP_FILTER_ALL;
+		cfg->rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
 	default:
 		return -ERANGE;
@@ -131,20 +129,20 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr)
 	/* Commit back the result & save it */
 	mutex_lock(&sparx5->ptp_lock);
 	phc = &sparx5->phc[SPARX5_PHC_PORT];
-	memcpy(&phc->hwtstamp_config, &cfg, sizeof(cfg));
+	phc->hwtstamp_config = *cfg;
 	mutex_unlock(&sparx5->ptp_lock);
 
-	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+	return 0;
 }
 
-int sparx5_ptp_hwtstamp_get(struct sparx5_port *port, struct ifreq *ifr)
+void sparx5_ptp_hwtstamp_get(struct sparx5_port *port,
+			     struct kernel_hwtstamp_config *cfg)
 {
 	struct sparx5 *sparx5 = port->sparx5;
 	struct sparx5_phc *phc;
 
 	phc = &sparx5->phc[SPARX5_PHC_PORT];
-	return copy_to_user(ifr->ifr_data, &phc->hwtstamp_config,
-			    sizeof(phc->hwtstamp_config)) ? -EFAULT : 0;
+	*cfg = phc->hwtstamp_config;
 }
 
 static void sparx5_ptp_classify(struct sparx5_port *port, struct sk_buff *skb,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 09/12] net: lan966x: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (7 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller Vladimir Oltean
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

The hardware timestamping through ndo_eth_ioctl() is going away.
Convert the lan966x driver to the new API before that can be removed.

After removing the timestamping logic from lan966x_port_ioctl(), the
rest is equivalent to phy_do_ioctl().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com>
---
Changes in v8:
- Use phy_do_ioctl()
Changes in v7:
- Patch is new

 .../ethernet/microchip/lan966x/lan966x_main.c | 59 +++++++++++--------
 .../ethernet/microchip/lan966x/lan966x_main.h | 12 ++--
 .../ethernet/microchip/lan966x/lan966x_ptp.c  | 34 +++++------
 3 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index fbb0bb4594cd..b0f614fbc5db 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -449,39 +449,44 @@ static int lan966x_port_get_parent_id(struct net_device *dev,
 	return 0;
 }
 
-static int lan966x_port_ioctl(struct net_device *dev, struct ifreq *ifr,
-			      int cmd)
+static int lan966x_port_hwtstamp_get(struct net_device *dev,
+				     struct kernel_hwtstamp_config *cfg)
 {
 	struct lan966x_port *port = netdev_priv(dev);
-	int err;
 
-	if (cmd == SIOCSHWTSTAMP) {
-		err = lan966x_ptp_setup_traps(port, ifr);
-		if (err)
-			return err;
-	}
+	if (phy_has_hwtstamp(dev->phydev))
+		return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP);
 
-	if (!phy_has_hwtstamp(dev->phydev) && port->lan966x->ptp) {
-		switch (cmd) {
-		case SIOCSHWTSTAMP:
-			err = lan966x_ptp_hwtstamp_set(port, ifr);
-			if (err)
-				lan966x_ptp_del_traps(port);
+	if (!port->lan966x->ptp)
+		return -EOPNOTSUPP;
 
-			return err;
-		case SIOCGHWTSTAMP:
-			return lan966x_ptp_hwtstamp_get(port, ifr);
-		}
-	}
+	lan966x_ptp_hwtstamp_get(port, cfg);
 
-	if (!dev->phydev)
-		return -ENODEV;
+	return 0;
+}
 
-	err = phy_mii_ioctl(dev->phydev, ifr, cmd);
-	if (err && cmd == SIOCSHWTSTAMP)
-		lan966x_ptp_del_traps(port);
+static int lan966x_port_hwtstamp_set(struct net_device *dev,
+				     struct kernel_hwtstamp_config *cfg,
+				     struct netlink_ext_ack *extack)
+{
+	struct lan966x_port *port = netdev_priv(dev);
+	int err;
 
-	return err;
+	err = lan966x_ptp_setup_traps(port, cfg);
+	if (err)
+		return err;
+
+	if (phy_has_hwtstamp(dev->phydev)) {
+		err = phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP);
+		if (err)
+			lan966x_ptp_del_traps(port);
+		return err;
+	}
+
+	if (!port->lan966x->ptp)
+		return -EOPNOTSUPP;
+
+	return lan966x_ptp_hwtstamp_set(port, cfg, extack);
 }
 
 static const struct net_device_ops lan966x_port_netdev_ops = {
@@ -494,10 +499,12 @@ static const struct net_device_ops lan966x_port_netdev_ops = {
 	.ndo_get_stats64		= lan966x_stats_get,
 	.ndo_set_mac_address		= lan966x_port_set_mac_address,
 	.ndo_get_port_parent_id		= lan966x_port_get_parent_id,
-	.ndo_eth_ioctl			= lan966x_port_ioctl,
+	.ndo_eth_ioctl			= phy_do_ioctl,
 	.ndo_setup_tc			= lan966x_tc_setup,
 	.ndo_bpf			= lan966x_xdp,
 	.ndo_xdp_xmit			= lan966x_xdp_xmit,
+	.ndo_hwtstamp_get		= lan966x_port_hwtstamp_get,
+	.ndo_hwtstamp_set		= lan966x_port_hwtstamp_set,
 };
 
 bool lan966x_netdevice_check(const struct net_device *dev)
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
index 27f272831ea5..b538d496e8d7 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
@@ -298,7 +298,7 @@ struct lan966x_phc {
 	struct ptp_clock *clock;
 	struct ptp_clock_info info;
 	struct ptp_pin_desc pins[LAN966X_PHC_PINS_NUM];
-	struct hwtstamp_config hwtstamp_config;
+	struct kernel_hwtstamp_config hwtstamp_config;
 	struct lan966x *lan966x;
 	u8 index;
 };
@@ -578,8 +578,11 @@ void lan966x_mdb_restore_entries(struct lan966x *lan966x);
 
 int lan966x_ptp_init(struct lan966x *lan966x);
 void lan966x_ptp_deinit(struct lan966x *lan966x);
-int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr);
-int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr);
+int lan966x_ptp_hwtstamp_set(struct lan966x_port *port,
+			     struct kernel_hwtstamp_config *cfg,
+			     struct netlink_ext_ack *extack);
+void lan966x_ptp_hwtstamp_get(struct lan966x_port *port,
+			      struct kernel_hwtstamp_config *cfg);
 void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb,
 			  u64 src_port, u64 timestamp);
 int lan966x_ptp_txtstamp_request(struct lan966x_port *port,
@@ -590,7 +593,8 @@ irqreturn_t lan966x_ptp_irq_handler(int irq, void *args);
 irqreturn_t lan966x_ptp_ext_irq_handler(int irq, void *args);
 u32 lan966x_ptp_get_period_ps(void);
 int lan966x_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
-int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr);
+int lan966x_ptp_setup_traps(struct lan966x_port *port,
+			    struct kernel_hwtstamp_config *cfg);
 int lan966x_ptp_del_traps(struct lan966x_port *port);
 
 int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
index 266a21a2d124..60bd0cff6677 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
@@ -248,29 +248,23 @@ int lan966x_ptp_del_traps(struct lan966x_port *port)
 	return err;
 }
 
-int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr)
+int lan966x_ptp_setup_traps(struct lan966x_port *port,
+			    struct kernel_hwtstamp_config *cfg)
 {
-	struct hwtstamp_config cfg;
-
-	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
-		return -EFAULT;
-
-	if (cfg.rx_filter == HWTSTAMP_FILTER_NONE)
+	if (cfg->rx_filter == HWTSTAMP_FILTER_NONE)
 		return lan966x_ptp_del_traps(port);
 	else
 		return lan966x_ptp_add_traps(port);
 }
 
-int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
+int lan966x_ptp_hwtstamp_set(struct lan966x_port *port,
+			     struct kernel_hwtstamp_config *cfg,
+			     struct netlink_ext_ack *extack)
 {
 	struct lan966x *lan966x = port->lan966x;
-	struct hwtstamp_config cfg;
 	struct lan966x_phc *phc;
 
-	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
-		return -EFAULT;
-
-	switch (cfg.tx_type) {
+	switch (cfg->tx_type) {
 	case HWTSTAMP_TX_ON:
 		port->ptp_tx_cmd = IFH_REW_OP_TWO_STEP_PTP;
 		break;
@@ -284,7 +278,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
 		return -ERANGE;
 	}
 
-	switch (cfg.rx_filter) {
+	switch (cfg->rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		port->ptp_rx_cmd = false;
 		break;
@@ -303,7 +297,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 	case HWTSTAMP_FILTER_NTP_ALL:
 		port->ptp_rx_cmd = true;
-		cfg.rx_filter = HWTSTAMP_FILTER_ALL;
+		cfg->rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
 	default:
 		return -ERANGE;
@@ -312,20 +306,20 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
 	/* Commit back the result & save it */
 	mutex_lock(&lan966x->ptp_lock);
 	phc = &lan966x->phc[LAN966X_PHC_PORT];
-	memcpy(&phc->hwtstamp_config, &cfg, sizeof(cfg));
+	phc->hwtstamp_config = *cfg;
 	mutex_unlock(&lan966x->ptp_lock);
 
-	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+	return 0;
 }
 
-int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr)
+void lan966x_ptp_hwtstamp_get(struct lan966x_port *port,
+			      struct kernel_hwtstamp_config *cfg)
 {
 	struct lan966x *lan966x = port->lan966x;
 	struct lan966x_phc *phc;
 
 	phc = &lan966x->phc[LAN966X_PHC_PORT];
-	return copy_to_user(ifr->ifr_data, &phc->hwtstamp_config,
-			    sizeof(phc->hwtstamp_config)) ? -EFAULT : 0;
+	*cfg = phc->hwtstamp_config;
 }
 
 static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (8 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 09/12] net: lan966x: " Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-18 14:31   ` Russell King (Oracle)
  2023-07-17 15:27 ` [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations Vladimir Oltean
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

phy_init() and phy_exit() will have to do more stuff under rtnl_lock()
in a future change. Since rtnl_unlock() -> netdev_run_todo() does a lot
of stuff under the hood, it's a pity to lock and unlock the rtnetlink
mutex twice in a row.

Change the calling convention such that the only caller of
ethtool_set_ethtool_phy_ops(), phy_device.c, provides a context where
the rtnl_mutex is already acquired.

Note that phy_exit() wasn't performing the opposite teardown of
phy_init(). Reverse mdio_bus_init() with ethtool_set_ethtool_phy_ops(),
so that this is now the case.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Changes in v8:
- Patch is new

 drivers/net/phy/phy_device.c | 8 +++++++-
 net/ethtool/common.c         | 3 +--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0c2014accba7..ab53d10f1844 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -30,6 +30,7 @@
 #include <linux/phy_led_triggers.h>
 #include <linux/pse-pd/pse.h>
 #include <linux/property.h>
+#include <linux/rtnetlink.h>
 #include <linux/sfp.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -3451,11 +3452,14 @@ static int __init phy_init(void)
 {
 	int rc;
 
+	rtnl_lock();
+	ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
+	rtnl_unlock();
+
 	rc = mdio_bus_init();
 	if (rc)
 		return rc;
 
-	ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
 	features_init();
 
 	rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
@@ -3477,7 +3481,9 @@ static void __exit phy_exit(void)
 	phy_driver_unregister(&genphy_c45_driver);
 	phy_driver_unregister(&genphy_driver);
 	mdio_bus_exit();
+	rtnl_lock();
 	ethtool_set_ethtool_phy_ops(NULL);
+	rtnl_unlock();
 }
 
 subsys_initcall(phy_init);
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index 5fb19050991e..f5598c5f50de 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -665,9 +665,8 @@ const struct ethtool_phy_ops *ethtool_phy_ops;
 
 void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops)
 {
-	rtnl_lock();
+	ASSERT_RTNL();
 	ethtool_phy_ops = ops;
-	rtnl_unlock();
 }
 EXPORT_SYMBOL_GPL(ethtool_set_ethtool_phy_ops);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (9 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-18  8:36   ` Vladimir Oltean
  2023-07-17 15:27 ` [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers Vladimir Oltean
  2023-07-18  8:39 ` [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
  12 siblings, 1 reply; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

net/core/dev_ioctl.c (built-in code) will want to call phy_mii_ioctl()
for hardware timestamping purposes. This is not directly possible,
because phy_mii_ioctl() is a symbol provided under CONFIG_PHYLIB.

Do something similar to what was done in DSA in commit 5a17818682cf
("net: dsa: replace NETDEV_PRE_CHANGE_HWTSTAMP notifier with a stub"),
and arrange some indirect calls to phy_mii_ioctl() through a stub
structure containing function pointers, that's provided by phylib as
built-in even when CONFIG_PHYLIB=m, and which phy_init() populates at
runtime (module insertion).

Note: maybe the ownership of the ethtool_phy_ops singleton is backwards,
and the methods exposed by that should be later merged into phylib_stubs.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Changes in v8:
- Patch is new

 drivers/net/phy/Makefile     |  2 ++
 drivers/net/phy/phy.c        | 34 ++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c | 18 ++++++++++++++++++
 include/linux/phy.h          |  7 +++++++
 4 files changed, 61 insertions(+)

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 2fe51ea83bab..5b5b0d300220 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -14,6 +14,8 @@ endif
 # dedicated loadable module, so we bundle them all together into libphy.ko
 ifdef CONFIG_PHYLIB
 libphy-y			+= $(mdio-bus-y)
+# the stubs are built-in whenever PHYLIB is built-in or module
+obj-y				+= stubs.o
 else
 obj-$(CONFIG_MDIO_DEVICE)	+= mdio-bus.o
 endif
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index bdf00b2b2c1d..8aec8e83038c 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -455,6 +455,40 @@ int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd)
 }
 EXPORT_SYMBOL(phy_do_ioctl_running);
 
+/**
+ * __phy_hwtstamp_get - Get hardware timestamping configuration from PHY
+ *
+ * @phydev: the PHY device structure
+ * @config: structure holding the timestamping configuration
+ *
+ * Query the PHY device for its current hardware timestamping configuration.
+ */
+int __phy_hwtstamp_get(struct phy_device *phydev,
+		       struct kernel_hwtstamp_config *config)
+{
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
+}
+
+/**
+ * __phy_hwtstamp_set - Modify PHY hardware timestamping configuration
+ *
+ * @phydev: the PHY device structure
+ * @config: structure holding the timestamping configuration
+ * @extack: netlink extended ack structure, for error reporting
+ */
+int __phy_hwtstamp_set(struct phy_device *phydev,
+		       struct kernel_hwtstamp_config *config,
+		       struct netlink_ext_ack *extack)
+{
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
+}
+
 /**
  * phy_queue_state_machine - Trigger the state machine to run soon
  *
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index ab53d10f1844..08c162b7e6be 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -27,6 +27,7 @@
 #include <linux/of.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
+#include <linux/phylib_stubs.h>
 #include <linux/phy_led_triggers.h>
 #include <linux/pse-pd/pse.h>
 #include <linux/property.h>
@@ -3448,12 +3449,28 @@ static const struct ethtool_phy_ops phy_ethtool_phy_ops = {
 	.start_cable_test_tdr	= phy_start_cable_test_tdr,
 };
 
+static const struct phylib_stubs __phylib_stubs = {
+	.hwtstamp_get = __phy_hwtstamp_get,
+	.hwtstamp_set = __phy_hwtstamp_set,
+};
+
+static void phylib_register_stubs(void)
+{
+	phylib_stubs = &__phylib_stubs;
+}
+
+static void phylib_unregister_stubs(void)
+{
+	phylib_stubs = NULL;
+}
+
 static int __init phy_init(void)
 {
 	int rc;
 
 	rtnl_lock();
 	ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
+	phylib_register_stubs();
 	rtnl_unlock();
 
 	rc = mdio_bus_init();
@@ -3483,6 +3500,7 @@ static void __exit phy_exit(void)
 	mdio_bus_exit();
 	rtnl_lock();
 	ethtool_set_ethtool_phy_ops(NULL);
+	phylib_unregister_stubs();
 	rtnl_unlock();
 }
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 11c1e91563d4..6710508e8c97 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -298,6 +298,7 @@ static inline const char *phy_modes(phy_interface_t interface)
 #define MII_BUS_ID_SIZE	61
 
 struct device;
+struct kernel_hwtstamp_config;
 struct phylink;
 struct sfp_bus;
 struct sfp_upstream_ops;
@@ -1954,6 +1955,12 @@ int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
 int phy_ethtool_get_plca_status(struct phy_device *phydev,
 				struct phy_plca_status *plca_st);
 
+int __phy_hwtstamp_get(struct phy_device *phydev,
+		       struct kernel_hwtstamp_config *config);
+int __phy_hwtstamp_set(struct phy_device *phydev,
+		       struct kernel_hwtstamp_config *config,
+		       struct netlink_ext_ack *extack);
+
 static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
 {
 	struct phy_package_shared *shared = phydev->shared;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (10 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations Vladimir Oltean
@ 2023-07-17 15:27 ` Vladimir Oltean
  2023-07-18 14:38   ` Russell King (Oracle)
  2023-07-18  8:39 ` [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
  12 siblings, 1 reply; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-17 15:27 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

It is desirable that the new .ndo_hwtstamp_set() API gives more
uniformity, less overhead and future flexibility w.r.t. the PHY
timestamping behavior.

Currently there are some drivers which allow PHY timestamping through
the procedure mentioned in Documentation/networking/timestamping.rst.
They don't do anything locally if phy_has_hwtstamp() is set, except for
lan966x which installs PTP packet traps.

Centralize that behavior in a new dev_set_hwtstamp_phylib() code
function, which calls either phy_mii_ioctl() for the phylib PHY,
or .ndo_hwtstamp_set() of the netdev, based on a single policy
(currently simplistic: phy_has_hwtstamp()).

Any driver converted to .ndo_hwtstamp_set() will automatically opt into
the centralized phylib timestamping policy. Unconverted drivers still
get to choose whether they let the PHY handle timestamping or not.

Netdev drivers with integrated PHY drivers that don't use phylib
presumably don't set dev->phydev, and those will always see
HWTSTAMP_SOURCE_NETDEV requests even when converted. The timestamping
policy will remain 100% up to them.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com>
---
Changes in v8:
- Replace direct phy_mii_ioctl() calls with indirect phy_hwtstamp_get()
  and phy_hwtstamp_set() stubs.
- Add missing kerneldoc for kernel_hwtstamp_config :: source.
Changes in v7:
- Patch is new

 drivers/net/ethernet/freescale/fec_main.c     |  8 --
 .../ethernet/microchip/lan966x/lan966x_main.c | 25 ++---
 .../ethernet/microchip/sparx5/sparx5_netdev.c |  6 --
 include/linux/net_tstamp.h                    | 16 ++++
 include/linux/netdevice.h                     |  4 +
 net/core/dev_ioctl.c                          | 91 +++++++++++++++++--
 6 files changed, 117 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 28c5f8f8106d..c66864f9d9ee 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3904,10 +3904,6 @@ static int fec_hwtstamp_get(struct net_device *ndev,
 			    struct kernel_hwtstamp_config *config)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phydev = ndev->phydev;
-
-	if (phy_has_hwtstamp(phydev))
-		return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
 
 	if (!fep->bufdesc_ex)
 		return -EOPNOTSUPP;
@@ -3922,10 +3918,6 @@ static int fec_hwtstamp_set(struct net_device *ndev,
 			    struct netlink_ext_ack *extack)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phydev = ndev->phydev;
-
-	if (phy_has_hwtstamp(phydev))
-		return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
 
 	if (!fep->bufdesc_ex)
 		return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index b0f614fbc5db..ef23153a48f1 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -454,9 +454,6 @@ static int lan966x_port_hwtstamp_get(struct net_device *dev,
 {
 	struct lan966x_port *port = netdev_priv(dev);
 
-	if (phy_has_hwtstamp(dev->phydev))
-		return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP);
-
 	if (!port->lan966x->ptp)
 		return -EOPNOTSUPP;
 
@@ -472,21 +469,26 @@ static int lan966x_port_hwtstamp_set(struct net_device *dev,
 	struct lan966x_port *port = netdev_priv(dev);
 	int err;
 
+	if (cfg->source != HWTSTAMP_SOURCE_NETDEV &&
+	    cfg->source != HWTSTAMP_SOURCE_PHYLIB)
+		return -EOPNOTSUPP;
+
 	err = lan966x_ptp_setup_traps(port, cfg);
 	if (err)
 		return err;
 
-	if (phy_has_hwtstamp(dev->phydev)) {
-		err = phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP);
-		if (err)
+	if (cfg->source == HWTSTAMP_SOURCE_NETDEV) {
+		if (!port->lan966x->ptp)
+			return -EOPNOTSUPP;
+
+		err = lan966x_ptp_hwtstamp_set(port, cfg, extack);
+		if (err) {
 			lan966x_ptp_del_traps(port);
-		return err;
+			return err;
+		}
 	}
 
-	if (!port->lan966x->ptp)
-		return -EOPNOTSUPP;
-
-	return lan966x_ptp_hwtstamp_set(port, cfg, extack);
+	return 0;
 }
 
 static const struct net_device_ops lan966x_port_netdev_ops = {
@@ -814,6 +816,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
 			 NETIF_F_HW_VLAN_STAG_TX |
 			 NETIF_F_HW_TC;
 	dev->hw_features |= NETIF_F_HW_TC;
+	dev->priv_flags |= IFF_SEE_ALL_HWTSTAMP_REQUESTS;
 	dev->needed_headroom = IFH_LEN_BYTES;
 
 	eth_hw_addr_gen(dev, lan966x->base_mac, p + 1);
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
index e01d3b1e17e0..705a004b324f 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
@@ -216,9 +216,6 @@ static int sparx5_port_hwtstamp_get(struct net_device *dev,
 	struct sparx5_port *sparx5_port = netdev_priv(dev);
 	struct sparx5 *sparx5 = sparx5_port->sparx5;
 
-	if (phy_has_hwtstamp(dev->phydev))
-		return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP);
-
 	if (!sparx5->ptp)
 		return -EOPNOTSUPP;
 
@@ -234,9 +231,6 @@ static int sparx5_port_hwtstamp_set(struct net_device *dev,
 	struct sparx5_port *sparx5_port = netdev_priv(dev);
 	struct sparx5 *sparx5 = sparx5_port->sparx5;
 
-	if (phy_has_hwtstamp(dev->phydev))
-		return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP);
-
 	if (!sparx5->ptp)
 		return -EOPNOTSUPP;
 
diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h
index 03e922814851..eb01c37e71e0 100644
--- a/include/linux/net_tstamp.h
+++ b/include/linux/net_tstamp.h
@@ -5,6 +5,11 @@
 
 #include <uapi/linux/net_tstamp.h>
 
+enum hwtstamp_source {
+	HWTSTAMP_SOURCE_NETDEV,
+	HWTSTAMP_SOURCE_PHYLIB,
+};
+
 /**
  * struct kernel_hwtstamp_config - Kernel copy of struct hwtstamp_config
  *
@@ -15,6 +20,8 @@
  *	a legacy implementation of a lower driver
  * @copied_to_user: request was passed to a legacy implementation which already
  *	copied the ioctl request back to user space
+ * @source: indication whether timestamps should come from the netdev or from
+ *	an attached phylib PHY
  *
  * Prefer using this structure for in-kernel processing of hardware
  * timestamping configuration, over the inextensible struct hwtstamp_config
@@ -26,6 +33,7 @@ struct kernel_hwtstamp_config {
 	int rx_filter;
 	struct ifreq *ifr;
 	bool copied_to_user;
+	enum hwtstamp_source source;
 };
 
 static inline void hwtstamp_config_to_kernel(struct kernel_hwtstamp_config *kernel_cfg,
@@ -44,4 +52,12 @@ static inline void hwtstamp_config_from_kernel(struct hwtstamp_config *cfg,
 	cfg->rx_filter = kernel_cfg->rx_filter;
 }
 
+static inline bool kernel_hwtstamp_config_changed(const struct kernel_hwtstamp_config *a,
+						  const struct kernel_hwtstamp_config *b)
+{
+	return a->flags != b->flags ||
+	       a->tx_type != b->tx_type ||
+	       a->rx_filter != b->rx_filter;
+}
+
 #endif /* _LINUX_NET_TIMESTAMPING_H_ */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ca3bcf2257c0..0d8a7ac67cf1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1724,6 +1724,9 @@ struct xdp_metadata_ops {
  * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with
  *	skb_headlen(skb) == 0 (data starts from frag0)
  * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN
+ * @IFF_SEE_ALL_HWTSTAMP_REQUESTS: device wants to see calls to
+ *	ndo_hwtstamp_set() for all timestamp requests regardless of source,
+ *	even if those aren't HWTSTAMP_SOURCE_NETDEV.
  */
 enum netdev_priv_flags {
 	IFF_802_1Q_VLAN			= 1<<0,
@@ -1759,6 +1762,7 @@ enum netdev_priv_flags {
 	IFF_NO_ADDRCONF			= BIT_ULL(30),
 	IFF_TX_SKB_NO_LINEAR		= BIT_ULL(31),
 	IFF_CHANGE_PROTO_DOWN		= BIT_ULL(32),
+	IFF_SEE_ALL_HWTSTAMP_REQUESTS	= BIT_ULL(33),
 };
 
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index d0223ecd6f6f..72e077022348 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -5,6 +5,7 @@
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/net_tstamp.h>
+#include <linux/phylib_stubs.h>
 #include <linux/wireless.h>
 #include <linux/if_bridge.h>
 #include <net/dsa_stubs.h>
@@ -252,6 +253,30 @@ static int dev_eth_ioctl(struct net_device *dev,
 	return ops->ndo_eth_ioctl(dev, ifr, cmd);
 }
 
+/**
+ * dev_get_hwtstamp_phylib() - Get hardware timestamping settings of NIC
+ *	or of attached phylib PHY
+ * @dev: Network device
+ * @cfg: Timestamping configuration structure
+ *
+ * Helper for enforcing a common policy that phylib timestamping, if available,
+ * should take precedence in front of hardware timestamping provided by the
+ * netdev.
+ *
+ * Note: phy_mii_ioctl() only handles SIOCSHWTSTAMP (not SIOCGHWTSTAMP), and
+ * there only exists a phydev->mii_ts->hwtstamp() method. So this will return
+ * -EOPNOTSUPP for phylib for now, which is still more accurate than letting
+ * the netdev handle the GET request.
+ */
+static int dev_get_hwtstamp_phylib(struct net_device *dev,
+				   struct kernel_hwtstamp_config *cfg)
+{
+	if (phy_has_hwtstamp(dev->phydev))
+		return phy_hwtstamp_get(dev->phydev, cfg);
+
+	return dev->netdev_ops->ndo_hwtstamp_get(dev, cfg);
+}
+
 static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
@@ -266,7 +291,7 @@ static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 		return -ENODEV;
 
 	kernel_cfg.ifr = ifr;
-	err = ops->ndo_hwtstamp_get(dev, &kernel_cfg);
+	err = dev_get_hwtstamp_phylib(dev, &kernel_cfg);
 	if (err)
 		return err;
 
@@ -283,6 +308,59 @@ static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 	return 0;
 }
 
+/**
+ * dev_set_hwtstamp_phylib() - Change hardware timestamping of NIC
+ *	or of attached phylib PHY
+ * @dev: Network device
+ * @cfg: Timestamping configuration structure
+ * @extack: Netlink extended ack message structure, for error reporting
+ *
+ * Helper for enforcing a common policy that phylib timestamping, if available,
+ * should take precedence in front of hardware timestamping provided by the
+ * netdev. If the netdev driver needs to perform specific actions even for PHY
+ * timestamping to work properly (a switch port must trap the timestamped
+ * frames and not forward them), it must set IFF_SEE_ALL_HWTSTAMP_REQUESTS in
+ * dev->priv_flags.
+ */
+static int dev_set_hwtstamp_phylib(struct net_device *dev,
+				   struct kernel_hwtstamp_config *cfg,
+				   struct netlink_ext_ack *extack)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+	bool phy_ts = phy_has_hwtstamp(dev->phydev);
+	struct kernel_hwtstamp_config old_cfg = {};
+	bool changed = false;
+	int err;
+
+	cfg->source = phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV;
+
+	if (!phy_ts || (dev->priv_flags & IFF_SEE_ALL_HWTSTAMP_REQUESTS)) {
+		err = ops->ndo_hwtstamp_get(dev, &old_cfg);
+		if (err)
+			return err;
+
+		err = ops->ndo_hwtstamp_set(dev, cfg, extack);
+		if (err) {
+			if (extack->_msg)
+				netdev_err(dev, "%s\n", extack->_msg);
+			return err;
+		}
+
+		changed = kernel_hwtstamp_config_changed(&old_cfg, cfg);
+	}
+
+	if (phy_ts) {
+		err = phy_hwtstamp_set(dev->phydev, cfg, extack);
+		if (err) {
+			if (changed)
+				ops->ndo_hwtstamp_set(dev, &old_cfg, NULL);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
 static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
@@ -314,12 +392,9 @@ static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
 	if (!netif_device_present(dev))
 		return -ENODEV;
 
-	err = ops->ndo_hwtstamp_set(dev, &kernel_cfg, &extack);
-	if (err) {
-		if (extack._msg)
-			netdev_err(dev, "%s\n", extack._msg);
+	err = dev_set_hwtstamp_phylib(dev, &kernel_cfg, &extack);
+	if (err)
 		return err;
-	}
 
 	/* The driver may have modified the configuration, so copy the
 	 * updated version of it back to user space
@@ -362,7 +437,7 @@ int generic_hwtstamp_get_lower(struct net_device *dev,
 		return -ENODEV;
 
 	if (ops->ndo_hwtstamp_get)
-		return ops->ndo_hwtstamp_get(dev, kernel_cfg);
+		return dev_get_hwtstamp_phylib(dev, kernel_cfg);
 
 	/* Legacy path: unconverted lower driver */
 	return generic_hwtstamp_ioctl_lower(dev, SIOCGHWTSTAMP, kernel_cfg);
@@ -379,7 +454,7 @@ int generic_hwtstamp_set_lower(struct net_device *dev,
 		return -ENODEV;
 
 	if (ops->ndo_hwtstamp_set)
-		return ops->ndo_hwtstamp_set(dev, kernel_cfg, extack);
+		return dev_set_hwtstamp_phylib(dev, kernel_cfg, extack);
 
 	/* Legacy path: unconverted lower driver */
 	return generic_hwtstamp_ioctl_lower(dev, SIOCSHWTSTAMP, kernel_cfg);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations
  2023-07-17 15:27 ` [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations Vladimir Oltean
@ 2023-07-18  8:36   ` Vladimir Oltean
  0 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-18  8:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Mon, Jul 17, 2023 at 06:27:08PM +0300, Vladimir Oltean wrote:
> net/core/dev_ioctl.c (built-in code) will want to call phy_mii_ioctl()
> for hardware timestamping purposes. This is not directly possible,
> because phy_mii_ioctl() is a symbol provided under CONFIG_PHYLIB.
> 
> Do something similar to what was done in DSA in commit 5a17818682cf
> ("net: dsa: replace NETDEV_PRE_CHANGE_HWTSTAMP notifier with a stub"),
> and arrange some indirect calls to phy_mii_ioctl() through a stub
> structure containing function pointers, that's provided by phylib as
> built-in even when CONFIG_PHYLIB=m, and which phy_init() populates at
> runtime (module insertion).
> 
> Note: maybe the ownership of the ethtool_phy_ops singleton is backwards,
> and the methods exposed by that should be later merged into phylib_stubs.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---

I should use "git add" on new files more often...

Annex to this patch:

diff --git a/drivers/net/phy/stubs.c b/drivers/net/phy/stubs.c
new file mode 100644
index 000000000000..06498de2d16a
--- /dev/null
+++ b/drivers/net/phy/stubs.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Stubs for PHY library functionality called by the core network stack.
+ * These are necessary because CONFIG_PHYLIB can be a module, and built-in
+ * code cannot directly call symbols exported by modules.
+ */
+#include <net/dsa_stubs.h>
+
+const struct phylib_stubs *phylib_stubs;
+EXPORT_SYMBOL_GPL(phylib_stubs);
diff --git a/include/linux/phylib_stubs.h b/include/linux/phylib_stubs.h
new file mode 100644
index 000000000000..1279f48c8a70
--- /dev/null
+++ b/include/linux/phylib_stubs.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Stubs for the Network PHY library
+ */
+
+#include <linux/rtnetlink.h>
+
+struct kernel_hwtstamp_config;
+struct netlink_ext_ack;
+struct phy_device;
+
+#if IS_ENABLED(CONFIG_PHYLIB)
+
+extern const struct phylib_stubs *phylib_stubs;
+
+struct phylib_stubs {
+	int (*hwtstamp_get)(struct phy_device *phydev,
+			    struct kernel_hwtstamp_config *config);
+	int (*hwtstamp_set)(struct phy_device *phydev,
+			    struct kernel_hwtstamp_config *config,
+			    struct netlink_ext_ack *extack);
+};
+
+static inline int phy_hwtstamp_get(struct phy_device *phydev,
+				   struct kernel_hwtstamp_config *config)
+{
+	/* phylib_register_stubs() and phylib_unregister_stubs()
+	 * also run under rtnl_lock().
+	 */
+	ASSERT_RTNL();
+
+	if (!phylib_stubs)
+		return -EOPNOTSUPP;
+
+	return phylib_stubs->hwtstamp_get(phydev, config);
+}
+
+static inline int phy_hwtstamp_set(struct phy_device *phydev,
+				   struct kernel_hwtstamp_config *config,
+				   struct netlink_ext_ack *extack)
+{
+	/* phylib_register_stubs() and phylib_unregister_stubs()
+	 * also run under rtnl_lock().
+	 */
+	ASSERT_RTNL();
+
+	if (!phylib_stubs)
+		return -EOPNOTSUPP;
+
+	return phylib_stubs->hwtstamp_set(phydev, config, extack);
+}
+
+#else
+
+static inline int phy_hwtstamp_get(struct phy_device *phydev,
+				   struct kernel_hwtstamp_config *config)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int phy_hwtstamp_set(struct phy_device *phydev,
+				   struct kernel_hwtstamp_config *config,
+				   struct netlink_ext_ack *extack)
+{
+	return -EOPNOTSUPP;
+}
+
+#endif

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
                   ` (11 preceding siblings ...)
  2023-07-17 15:27 ` [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers Vladimir Oltean
@ 2023-07-18  8:39 ` Vladimir Oltean
  12 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-18  8:39 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Mon, Jul 17, 2023 at 06:26:57PM +0300, Vladimir Oltean wrote:
> Based on previous RFCs from Maxim Georgiev:
> https://lore.kernel.org/netdev/20230502043150.17097-1-glipus@gmail.com/
> 
> this series attempts to introduce new API for the hardware timestamping
> control path (SIOCGHWTSTAMP and SIOCSHWTSTAMP handling).
> 
> I don't have any board with phylib hardware timestamping, so I would
> appreciate testing (especially on lan966x, the most intricate
> conversion). I was, however, able to test netdev level timestamping,
> because I also have some more unsubmitted conversions in progress:
> 
> https://github.com/vladimiroltean/linux/commits/ndo-hwtstamp-v7
> 
> I hope that the concerns expressed in the comments of previous series
> were addressed, and that Köry Maincent's series:
> https://lore.kernel.org/netdev/20230406173308.401924-1-kory.maincent@bootlin.com/
> can make progress in parallel with the conversion of the rest of drivers.

I'll be waiting until the end of today for more feedback, then I'll
resend this with all the pieces actually added to the commit (and with
include/linux/phylib_stubs.h part of the ETHERNET PHY LIBRARY entry in
MAINTAINERS).

pw-bot: cr

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-17 15:27 ` [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
@ 2023-07-18 14:06   ` Steen Hegelund
  0 siblings, 0 replies; 21+ messages in thread
From: Steen Hegelund @ 2023-07-18 14:06 UTC (permalink / raw)
  To: Vladimir Oltean, netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Maxim Georgiev, Horatiu Vultur,
	Köry Maincent, Maxime Chevallier, Richard Cochran,
	Vadim Fedorenko, Gerhard Engleder, Hangbin Liu, Russell King,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Daniel Machon, Simon Horman,
	Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

Hi Vladimir,

On Mon, 2023-07-17 at 18:27 +0300, Vladimir Oltean wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> The hardware timestamping through ndo_eth_ioctl() is going away.
> Convert the sparx5 driver to the new API before that can be removed.
> 
> After removing the timestamping logic from sparx5_port_ioctl(), the rest
> is equivalent to phy_do_ioctl().
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
> Changes in v8:
> - Use phy_do_ioctl()
> Changes in v7:
> - Patch is new
> 
> 

...[snip]...

>  static void sparx5_ptp_classify(struct sparx5_port *port, struct sk_buff
> *skb,
> --
> 2.34.1
> 

Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>

BR
Steen

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-17 15:27 ` [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
@ 2023-07-18 14:20   ` Russell King (Oracle)
  2023-08-01 13:12     ` Vladimir Oltean
  0 siblings, 1 reply; 21+ messages in thread
From: Russell King (Oracle) @ 2023-07-18 14:20 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Andrew Lunn, Florian Fainelli, Maxim Georgiev,
	Horatiu Vultur, Köry Maincent, Maxime Chevallier,
	Richard Cochran, Vadim Fedorenko, Gerhard Engleder, Hangbin Liu,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Mon, Jul 17, 2023 at 06:27:03PM +0300, Vladimir Oltean wrote:
> -static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
> -{
> -	struct fec_enet_private *fep = netdev_priv(ndev);
> -	struct phy_device *phydev = ndev->phydev;
> -
> -	if (!netif_running(ndev))
> -		return -EINVAL;
> -
> -	if (!phydev)
> -		return -ENODEV;
> -
... process hwtstamp calls

So if the network device is not running, ioctl() returns -EINVAL. From
what I can see in fec_enet_mii_probe() called from fec_enet_open(), we
guarantee that phydev will not be NULL once the first open has
succeeded, so I don't think the second if() statement has any effect.

> +static int fec_hwtstamp_get(struct net_device *ndev,
> +			    struct kernel_hwtstamp_config *config)
> +{
> +	struct fec_enet_private *fep = netdev_priv(ndev);
> +	struct phy_device *phydev = ndev->phydev;
> +
> +	if (phy_has_hwtstamp(phydev))
> +		return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
> +
> +	if (!fep->bufdesc_ex)
> +		return -EOPNOTSUPP;

If the interface hasn't been brought up at least once, then phydev
here will be NULL, and we'll drop through to this test. If the FEC
doesn't support extended buffer descriptors, userspace will see
-EOPNOTSUPP rather than -EINVAL. This could be misleading to userspace.

Does this need something like:

	if (!netif_running(ndev))
		return -EINVAL;

before, or maybe just after phy_has_hwtstamp() to give equivalent
behaviour?

> +static int fec_hwtstamp_set(struct net_device *ndev,
> +			    struct kernel_hwtstamp_config *config,
> +			    struct netlink_ext_ack *extack)
> +{
> +	struct fec_enet_private *fep = netdev_priv(ndev);
> +	struct phy_device *phydev = ndev->phydev;
> +
> +	if (phy_has_hwtstamp(phydev)) {
> +		fec_ptp_disable_hwts(ndev);
> +
> +		return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
> +	}
> +
> +	if (!fep->bufdesc_ex)
> +		return -EOPNOTSUPP;

Same comment here.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller
  2023-07-17 15:27 ` [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller Vladimir Oltean
@ 2023-07-18 14:31   ` Russell King (Oracle)
  0 siblings, 0 replies; 21+ messages in thread
From: Russell King (Oracle) @ 2023-07-18 14:31 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Andrew Lunn, Florian Fainelli, Maxim Georgiev,
	Horatiu Vultur, Köry Maincent, Maxime Chevallier,
	Richard Cochran, Vadim Fedorenko, Gerhard Engleder, Hangbin Liu,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Mon, Jul 17, 2023 at 06:27:07PM +0300, Vladimir Oltean wrote:
> phy_init() and phy_exit() will have to do more stuff under rtnl_lock()
> in a future change. Since rtnl_unlock() -> netdev_run_todo() does a lot
> of stuff under the hood, it's a pity to lock and unlock the rtnetlink
> mutex twice in a row.
> 
> Change the calling convention such that the only caller of
> ethtool_set_ethtool_phy_ops(), phy_device.c, provides a context where
> the rtnl_mutex is already acquired.
> 
> Note that phy_exit() wasn't performing the opposite teardown of
> phy_init(). Reverse mdio_bus_init() with ethtool_set_ethtool_phy_ops(),
> so that this is now the case.

To me, this looks buggy.

> @@ -3451,11 +3452,14 @@ static int __init phy_init(void)
>  {
>  	int rc;
>  
> +	rtnl_lock();
> +	ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
> +	rtnl_unlock();
> +
>  	rc = mdio_bus_init();
>  	if (rc)
>  		return rc;

If mdio_bus_init() fails, and phylib is built as a module, then we
leave ethtool_phy_ops pointing into module space that has potentially
been freed or re-used for another module. This error path needs to
properly clean up.

The same is also true for the other failure paths in phy_init() which
already do not cater for their failures leaving a dangling pointer in
ethtool_phy_ops. This should probably be fixed first in a separate
patch for the net tree.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers
  2023-07-17 15:27 ` [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers Vladimir Oltean
@ 2023-07-18 14:38   ` Russell King (Oracle)
  2023-07-18 14:46     ` Vladimir Oltean
  0 siblings, 1 reply; 21+ messages in thread
From: Russell King (Oracle) @ 2023-07-18 14:38 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Andrew Lunn, Florian Fainelli, Maxim Georgiev,
	Horatiu Vultur, Köry Maincent, Maxime Chevallier,
	Richard Cochran, Vadim Fedorenko, Gerhard Engleder, Hangbin Liu,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Mon, Jul 17, 2023 at 06:27:09PM +0300, Vladimir Oltean wrote:
> +static int dev_set_hwtstamp_phylib(struct net_device *dev,
> +				   struct kernel_hwtstamp_config *cfg,
> +				   struct netlink_ext_ack *extack)
> +{
> +	const struct net_device_ops *ops = dev->netdev_ops;
> +	bool phy_ts = phy_has_hwtstamp(dev->phydev);
> +	struct kernel_hwtstamp_config old_cfg = {};
> +	bool changed = false;
> +	int err;
> +
> +	cfg->source = phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV;
> +
> +	if (!phy_ts || (dev->priv_flags & IFF_SEE_ALL_HWTSTAMP_REQUESTS)) {

I suppose the idea here is that for something like mvpp2, which when we
have PTP support for Marvell PHYs in general will want to prefer to use
the MAC-based PTP rather than PHY-based, that driver needs to set
IFF_SEE_ALL_HWTSTAMP_REQUESTS so that the ndo timestamp ops always get
called? I didn't see this discussed in the commit message for this
patch.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers
  2023-07-18 14:38   ` Russell King (Oracle)
@ 2023-07-18 14:46     ` Vladimir Oltean
  0 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-07-18 14:46 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Andrew Lunn, Florian Fainelli, Maxim Georgiev,
	Horatiu Vultur, Köry Maincent, Maxime Chevallier,
	Richard Cochran, Vadim Fedorenko, Gerhard Engleder, Hangbin Liu,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Tue, Jul 18, 2023 at 03:38:27PM +0100, Russell King (Oracle) wrote:
> On Mon, Jul 17, 2023 at 06:27:09PM +0300, Vladimir Oltean wrote:
> > +static int dev_set_hwtstamp_phylib(struct net_device *dev,
> > +				   struct kernel_hwtstamp_config *cfg,
> > +				   struct netlink_ext_ack *extack)
> > +{
> > +	const struct net_device_ops *ops = dev->netdev_ops;
> > +	bool phy_ts = phy_has_hwtstamp(dev->phydev);
> > +	struct kernel_hwtstamp_config old_cfg = {};
> > +	bool changed = false;
> > +	int err;
> > +
> > +	cfg->source = phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV;
> > +
> > +	if (!phy_ts || (dev->priv_flags & IFF_SEE_ALL_HWTSTAMP_REQUESTS)) {
> 
> I suppose the idea here is that for something like mvpp2, which when we
> have PTP support for Marvell PHYs in general will want to prefer to use
> the MAC-based PTP rather than PHY-based, that driver needs to set
> IFF_SEE_ALL_HWTSTAMP_REQUESTS so that the ndo timestamp ops always get
> called? I didn't see this discussed in the commit message for this
> patch.

No; the plan for mvpp2-like situations is for Köry to:

- add UAPI to allow specifying the timestamping source (based on PHC ID,
  aka /dev/ptpN, probably)

- change the core policy (effectively this function) to prefer:
  - netdev-based timestamping by default (this reverses the current policy,
    to prevent future regressions when more phylib drivers gain
    timestamping support)
  - phylib-based timestamping for a selection of whitelisted phylib PHYs
    (this avoids regressions with existing phylib-based systems)
  - the user choice

The only thing that IFF_SEE_ALL_HWTSTAMP_REQUESTS does is to give the
netdev a hook for phylib timestamping operations, for completely
unrelated purposes (switch ports that become PTP-aware must stop
flooding PTP packets).

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
  2023-07-18 14:20   ` Russell King (Oracle)
@ 2023-08-01 13:12     ` Vladimir Oltean
  0 siblings, 0 replies; 21+ messages in thread
From: Vladimir Oltean @ 2023-08-01 13:12 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Andrew Lunn, Florian Fainelli, Maxim Georgiev,
	Horatiu Vultur, Köry Maincent, Maxime Chevallier,
	Richard Cochran, Vadim Fedorenko, Gerhard Engleder, Hangbin Liu,
	Heiner Kallweit, Jacob Keller, Jay Vosburgh, Andy Gospodarek,
	Wei Fang, Shenwei Wang, Clark Wang, NXP Linux Team,
	UNGLinuxDriver, Lars Povlsen, Steen Hegelund, Daniel Machon,
	Simon Horman, Casper Andersson, Sergey Organov, Michal Kubecek,
	linux-arm-kernel, linux-kernel

On Tue, Jul 18, 2023 at 03:20:13PM +0100, Russell King (Oracle) wrote:
> > +static int fec_hwtstamp_get(struct net_device *ndev,
> > +			    struct kernel_hwtstamp_config *config)
> > +{
> > +	struct fec_enet_private *fep = netdev_priv(ndev);
> > +	struct phy_device *phydev = ndev->phydev;
> > +
> > +	if (phy_has_hwtstamp(phydev))
> > +		return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
> > +
> > +	if (!fep->bufdesc_ex)
> > +		return -EOPNOTSUPP;
> 
> If the interface hasn't been brought up at least once, then phydev
> here will be NULL, and we'll drop through to this test. If the FEC
> doesn't support extended buffer descriptors, userspace will see
> -EOPNOTSUPP rather than -EINVAL. This could be misleading to userspace.
> 
> Does this need something like:
> 
> 	if (!netif_running(ndev))
> 		return -EINVAL;
> 
> before, or maybe just after phy_has_hwtstamp() to give equivalent
> behaviour?
> 
> > +static int fec_hwtstamp_set(struct net_device *ndev,
> > +			    struct kernel_hwtstamp_config *config,
> > +			    struct netlink_ext_ack *extack)
> > +{
> > +	struct fec_enet_private *fep = netdev_priv(ndev);
> > +	struct phy_device *phydev = ndev->phydev;
> > +
> > +	if (phy_has_hwtstamp(phydev)) {
> > +		fec_ptp_disable_hwts(ndev);
> > +
> > +		return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
> > +	}
> > +
> > +	if (!fep->bufdesc_ex)
> > +		return -EOPNOTSUPP;
> 
> Same comment here.

I will add back the netif_running() check to continue to not permit the
operation to go through, as before.

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2023-08-01 13:13 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-17 15:26 [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
2023-07-17 15:26 ` [PATCH v8 net-next 01/12] net: add NDOs for configuring hardware timestamping Vladimir Oltean
2023-07-17 15:26 ` [PATCH v8 net-next 02/12] net: add hwtstamping helpers for stackable net devices Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 03/12] net: vlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 04/12] net: macvlan: " Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 05/12] net: bonding: " Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
2023-07-18 14:20   ` Russell King (Oracle)
2023-08-01 13:12     ` Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 07/12] net: fec: delete fec_ptp_disable_hwts() Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean
2023-07-18 14:06   ` Steen Hegelund
2023-07-17 15:27 ` [PATCH v8 net-next 09/12] net: lan966x: " Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller Vladimir Oltean
2023-07-18 14:31   ` Russell King (Oracle)
2023-07-17 15:27 ` [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations Vladimir Oltean
2023-07-18  8:36   ` Vladimir Oltean
2023-07-17 15:27 ` [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers Vladimir Oltean
2023-07-18 14:38   ` Russell King (Oracle)
2023-07-18 14:46     ` Vladimir Oltean
2023-07-18  8:39 ` [PATCH v8 net-next 00/12] Introduce ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Oltean

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).