From patchwork Mon Jul 17 15:26:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316498 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8L-004NwG-0G for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:34 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 01/12] net: add NDOs for configuring hardware timestamping Date: Mon, 17 Jul 2023 18:26:58 +0300 Message-Id: <20230717152709.574773-2-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org From: Maxim Georgiev 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 Signed-off-by: Maxim Georgiev Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Tested-by: Horatiu Vultur --- 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, From patchwork Mon Jul 17 15:26:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316497 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8N-004NwG-0o for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:37 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 02/12] net: add hwtstamping helpers for stackable net devices Date: Mon, 17 Jul 2023 18:26:59 +0300 Message-Id: <20230717152709.574773-3-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org From: Maxim Georgiev 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 Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller --- 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) { From patchwork Mon Jul 17 15:27:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316500 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8P-004NwG-1m for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:38 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 03/12] net: vlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() Date: Mon, 17 Jul 2023 18:27:00 +0300 Message-Id: <20230717152709.574773-4-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org From: Maxim Georgiev 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 Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller --- 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) From patchwork Mon Jul 17 15:27:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316502 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8R-004NwG-23 for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:41 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 04/12] net: macvlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() Date: Mon, 17 Jul 2023 18:27:01 +0300 Message-Id: <20230717152709.574773-5-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org From: Maxim Georgiev 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 Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller --- 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) From patchwork Mon Jul 17 15:27:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316504 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8T-004NwG-2L for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:43 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 05/12] net: bonding: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() Date: Mon, 17 Jul 2023 18:27:02 +0300 Message-Id: <20230717152709.574773-6-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org From: Maxim Georgiev 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 Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller --- 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 = { From patchwork Mon Jul 17 15:27:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8V-004NwG-2M for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:45 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 06/12] net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Date: Mon, 17 Jul 2023 18:27:03 +0300 Message-Id: <20230717152709.574773-7-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 Reviewed-by: Jacob Keller Reviewed-by: Wei Fang --- 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); } /* From patchwork Mon Jul 17 15:27:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316506 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8X-004NwG-2d for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:47 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 07/12] net: fec: delete fec_ptp_disable_hwts() Date: Mon, 17 Jul 2023 18:27:04 +0300 Message-Id: <20230717152709.574773-8-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 Reviewed-by: Jacob Keller Reviewed-by: Wei Fang --- 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) { From patchwork Mon Jul 17 15:27:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316507 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8Z-004NwG-2c for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:49 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 08/12] net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Date: Mon, 17 Jul 2023 18:27:05 +0300 Message-Id: <20230717152709.574773-9-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 Reviewed-by: Jacob Keller Reviewed-by: Steen Hegelund --- 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, From patchwork Mon Jul 17 15:27:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316503 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8c-004NwG-03 for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:52 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 09/12] net: lan966x: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Date: Mon, 17 Jul 2023 18:27:06 +0300 Message-Id: <20230717152709.574773-10-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 Reviewed-by: Jacob Keller Tested-by: Horatiu Vultur --- 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) From patchwork Mon Jul 17 15:27:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316508 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8e-004NwG-2S for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:55 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 10/12] net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller Date: Mon, 17 Jul 2023 18:27:07 +0300 Message-Id: <20230717152709.574773-11-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 --- 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 #include #include +#include #include #include #include @@ -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); From patchwork Mon Jul 17 15:27:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316511 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-he1eur04on062a.outbound.protection.outlook.com ([2a01:111:f400:fe0d::62a] helo=EUR04-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8i-004NwG-1D for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:58 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations Date: Mon, 17 Jul 2023 18:27:08 +0300 Message-Id: <20230717152709.574773-12-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 --- 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 #include #include +#include #include #include #include @@ -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; From patchwork Mon Jul 17 15:27:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 13316510 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail-dbaeur03on20606.outbound.protection.outlook.com ([2a01:111:f400:fe1a::606] helo=EUR03-DBA-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qLQ8d-004O7z-2j for linux-arm-kernel@lists.infradead.org; Mon, 17 Jul 2023 15:27:54 +0000 From: Vladimir Oltean Subject: [PATCH v8 net-next 12/12] net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers Date: Mon, 17 Jul 2023 18:27:09 +0300 Message-Id: <20230717152709.574773-13-vladimir.oltean@nxp.com> In-Reply-To: <20230717152709.574773-1-vladimir.oltean@nxp.com> References: <20230717152709.574773-1-vladimir.oltean@nxp.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Florian Fainelli , Maxim Georgiev , Horatiu Vultur , =?utf-8?q?K=C3=B6ry_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@microchip.com, Lars Povlsen , Steen Hegelund , Daniel Machon , Simon Horman , Casper Andersson , Sergey Organov , Michal Kubecek , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org 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 Reviewed-by: Jacob Keller Tested-by: Horatiu Vultur --- 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 +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 #include #include +#include #include #include #include @@ -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);