From nobody Sun Dec 14 19:14:01 2025 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94E8422332B; Thu, 12 Dec 2024 17:07:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023231; cv=none; b=CMoOIAHIKeScUoPb8osr5k8y+u+eBvB47N0KiO3HaL9LT2LjSknuM/wgsjILdsGjfLUk3dkqFaacnoa9HmlAvyoRr5q7yIO38UUzpmJj+JGzXtXCvrLBS1v2/2eO4FxaEGJTofusNp96TZGi8L8a7aINhWlnaTrUSdIPwtb56ao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023231; c=relaxed/simple; bh=RYbZJtucpSigeMYPdtI0+z6/SDVinaJQBiQLbpoHf+E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dMc66d32WXL2Zj2rp87u0SCDLmJVSDZ08weLHDmnfgmsaa39aiZx3O4DvqWtW/MW42BJnbmQpjQMLy1Dsp9/X3+9Up1SfkEqgOqhmoUV86Fk2v2XUMsBNFmRZ+RN8aCpjRT9SFdyoEyI54u0SbU60dNvMdV7+2LEFxZBwPnSjh4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=cV89OMS5; arc=none smtp.client-ip=217.70.183.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="cV89OMS5" Received: by mail.gandi.net (Postfix) with ESMTPSA id 12D0960002; Thu, 12 Dec 2024 17:06:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734023221; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=msvoSwtKy3Xw3ahbD1M7vZdznKOSerhqCQxIPQ0W5ME=; b=cV89OMS52qTlCt/+UdMwCBW6+wws6W+ifkEQXgBigBQtF5tnEFhF73J966kyTbGAKYy20t ruN4KjmDedMF9YdNZ8NduTH7tJBsRaW+tzg5m8aT/kikAVH0U+1+oenvp4LbekRRF3vVx0 r2EZsTVVqyQSHNSak+8kmB6/k2AejneFgfXFrKuBeCXoV+9V1J+IqqvClTB4bSFsZxTYxo VVmhhFNcsS8pizgaeLfJ3mfGzQlEspxZpg4pI7IVaUQ/PGlibi5AftldkM2qGPUUJgq734 LKchRU1/oj2WWg99vQGsgnpU9+j2uiqzC+GzBPZEwkdEq4CB2tkZj3K5Ys/qmQ== From: Kory Maincent Date: Thu, 12 Dec 2024 18:06:41 +0100 Subject: [PATCH net-next v21 1/5] net: Make dev_get_hwtstamp_phylib accessible Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241212-feature_ptp_netnext-v21-1-2c282a941518@bootlin.com> References: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> In-Reply-To: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> To: Florian Fainelli , Broadcom internal kernel review list , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Radu Pirea , Jay Vosburgh , Andy Gospodarek , Nicolas Ferre , Claudiu Beznea , Willem de Bruijn , Jonathan Corbet , Horatiu Vultur , UNGLinuxDriver@microchip.com, Simon Horman , Vladimir Oltean , donald.hunter@gmail.com, danieller@nvidia.com, ecree.xilinx@gmail.com, Andrew Lunn Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-doc@vger.kernel.org, Maxime Chevallier , Rahul Rameshbabu , Willem de Bruijn , Shannon Nelson , Alexandra Winter , Kory Maincent , Jacob Keller X-Mailer: b4 0.14.1 X-GND-Sasl: kory.maincent@bootlin.com Make the dev_get_hwtstamp_phylib function accessible in prevision to use it from ethtool to read the hwtstamp current configuration. Reviewed-by: Florian Fainelli Reviewed-by: Jacob Keller Signed-off-by: Kory Maincent --- Change in v8: - New patch Change in v10: - Remove export symbol as ethtool can't be built as a module. - Move the declaration to net/core/dev.h instead of netdevice.h --- net/core/dev.h | 2 ++ net/core/dev_ioctl.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/core/dev.h b/net/core/dev.h index d043dee25a68..357543cbde65 100644 --- a/net/core/dev.h +++ b/net/core/dev.h @@ -310,5 +310,7 @@ static inline void dev_xmit_recursion_dec(void) int dev_set_hwtstamp_phylib(struct net_device *dev, struct kernel_hwtstamp_config *cfg, struct netlink_ext_ack *extack); +int dev_get_hwtstamp_phylib(struct net_device *dev, + struct kernel_hwtstamp_config *cfg); =20 #endif diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 46d43b950471..67cf68817f23 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -266,8 +266,8 @@ static int dev_eth_ioctl(struct net_device *dev, * -EOPNOTSUPP for phylib for now, which is still more accurate than letti= ng * the netdev handle the GET request. */ -static int dev_get_hwtstamp_phylib(struct net_device *dev, - struct kernel_hwtstamp_config *cfg) +int dev_get_hwtstamp_phylib(struct net_device *dev, + struct kernel_hwtstamp_config *cfg) { if (phy_is_default_hwtstamp(dev->phydev)) return phy_hwtstamp_get(dev->phydev, cfg); --=20 2.34.1 From nobody Sun Dec 14 19:14:01 2025 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 645CB222D75; Thu, 12 Dec 2024 17:07:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023229; cv=none; b=n/t1mT60hgJJgShJuA8Q57hbk4goKzwkqo7YSSClLBKg8Wiu+VBFrgD33kbfjHPcVsZBqLb/2MZSDONsdDxrO+NXNulz3mdvYPq/NgIWFhKHw0tJ/XD/TzP1yOoJGHe1cR+tv+U4zfjpfusSGCzGW6PuDCuZOvHo7NJktgplNGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023229; c=relaxed/simple; bh=ZjvHZkc5inY+pRASyJgpQhjoZd37S6DxzdVDTHf6W+I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QT2E4/Wn3ElWzOKmMW1AhU0RBhPPeC1cyVxz6xZnufesxc8c9CvgRPa1ow18CbGlk4gukwM1NSUM6y6Dt7wF7Q1b7wuZCkLPF7UGNBdWfn7TznY4UQMgDy1ymMnjXOhsHprNSQ2NWxAmMNN49AqD4mNHPbz2ty94f6uy2j8Pn6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=LmMSw1JO; arc=none smtp.client-ip=217.70.183.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="LmMSw1JO" Received: by mail.gandi.net (Postfix) with ESMTPSA id 92BE96000B; Thu, 12 Dec 2024 17:07:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734023224; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uMy6XiHeL00a21AbpVvnbAktcJJ0pCxX4TSIpkEjL+M=; b=LmMSw1JO3XrnRUJGR/ff9c1mi6Ye10Uv/qCOb5cCedCWwlj+6Wp33ExsypfmByCkwHGKBK UcDv9NHpXH26dWSjg84O+z0flpKP4P5u6ClydqVf2bxuu3v/p8UQWkX8w2JsdFUAfgBILZ Bu5WiYlCn7G0M1S0oiFO4a56Fvo0ZV1gwm+8rSEScZoqETJuV+3K1V7OBa1SV/AiRmnwJ+ yY91sPTfXb9U+7AlIhjVyFvRqiYz9jU2uD8cmyQiMb6vlJ7XFleeqqVLJNVnXeGX4osJ5K PbRG9/UOlOiepe1mGsMKXkkQ1Ml0sULtXjMAIBzPLLc13Csj0JsMPMjgxb3yIg== From: Kory Maincent Date: Thu, 12 Dec 2024 18:06:42 +0100 Subject: [PATCH net-next v21 2/5] net: Make net_hwtstamp_validate accessible Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241212-feature_ptp_netnext-v21-2-2c282a941518@bootlin.com> References: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> In-Reply-To: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> To: Florian Fainelli , Broadcom internal kernel review list , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Radu Pirea , Jay Vosburgh , Andy Gospodarek , Nicolas Ferre , Claudiu Beznea , Willem de Bruijn , Jonathan Corbet , Horatiu Vultur , UNGLinuxDriver@microchip.com, Simon Horman , Vladimir Oltean , donald.hunter@gmail.com, danieller@nvidia.com, ecree.xilinx@gmail.com, Andrew Lunn Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-doc@vger.kernel.org, Maxime Chevallier , Rahul Rameshbabu , Willem de Bruijn , Shannon Nelson , Alexandra Winter , Kory Maincent , Jacob Keller X-Mailer: b4 0.14.1 X-GND-Sasl: kory.maincent@bootlin.com Make the net_hwtstamp_validate function accessible in prevision to use it from ethtool to validate the hwtstamp configuration before setting it. Reviewed-by: Florian Fainelli Reviewed-by: Jacob Keller Signed-off-by: Kory Maincent --- Change in v8: - New patch Change in v10: - Remove export symbol as ethtool can't be built as a module. - Move the declaration to net/core/dev.h instead of netdevice.h --- net/core/dev.h | 1 + net/core/dev_ioctl.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.h b/net/core/dev.h index 357543cbde65..aa91eed55a40 100644 --- a/net/core/dev.h +++ b/net/core/dev.h @@ -312,5 +312,6 @@ int dev_set_hwtstamp_phylib(struct net_device *dev, struct netlink_ext_ack *extack); int dev_get_hwtstamp_phylib(struct net_device *dev, struct kernel_hwtstamp_config *cfg); +int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg); =20 #endif diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 67cf68817f23..1f09930fca26 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -184,7 +184,7 @@ static int dev_ifsioc_locked(struct net *net, struct if= req *ifr, unsigned int cm return err; } =20 -static int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg) +int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg) { enum hwtstamp_tx_types tx_type; enum hwtstamp_rx_filters rx_filter; --=20 2.34.1 From nobody Sun Dec 14 19:14:01 2025 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B82D72253F1; Thu, 12 Dec 2024 17:07:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023232; cv=none; b=Rl59wko/Si1bsQfrSXp4AwGtiA21hkhxFTmK2ewQnSfBElQdHN0Gl0Z3gWEFmKprJ/1Ov8CrzBXVAUNW/mKxp/bhz0Frw9O6ZZxATnXrXx8eUekB44tEzS4LtKR+IJB46C5jjYe1IVgerHFOhbUV1XrrxqVt8/pnD+cJlP/5Ux0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023232; c=relaxed/simple; bh=E+uE2DlNT+Eq6FJ/S24TNGS2baK6Dp71ui9EHV/qmM8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aPKpDjcrTt9lARjMZigEBNV7KxWF6FpAKigpBzGywR/5FXpXOJ5XlPnrV+vNthaTyDYn3OQt+2iUDMqjXTeqVu5HxuCKINliv6duWhvGuT5M0tAiNqIg9kLLni15pUAqygZzFI+tFcJNTba0GUurXBuTYVKOyI4Q6Zxxnf9TmYA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Fc3qBqps; arc=none smtp.client-ip=217.70.183.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Fc3qBqps" Received: by mail.gandi.net (Postfix) with ESMTPSA id B472560005; Thu, 12 Dec 2024 17:07:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734023228; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eWnGJ0OJb8yBGMbkiKUMbfrydHq7sBNjtIC5N9B6H2Q=; b=Fc3qBqpsZ26tVyjSX+FBUesm0A1HncJgiQqO85niiTZm5/buPBC5Zw7pduc83jK480t9Sv G1gtZAHQVaYG0yRgOwoC93nK9moi+1Un8sBLRRvx7+3yYOw6xvudccqFQ5K6o5nHqw1KUp eNI22dTBIyVotCzc9DwSI9+itsx2Cnfrif35Gt+SZQytxZ337hieezd0ehT05QngAWj4sj RAfY+1laDBoRfBCN/CDZU2KFHdyx9HNv68LNrVZQdjGiSy6OaNwP1iRzp04oFSzVXzbBhl 93xJp90p+vurRJhBzF0HVnOlpecchpQCJ/kfI5esNQmKcWy1YEId2k6M7rRfaA== From: Kory Maincent Date: Thu, 12 Dec 2024 18:06:43 +0100 Subject: [PATCH net-next v21 3/5] net: Add the possibility to support a selected hwtstamp in netdevice Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241212-feature_ptp_netnext-v21-3-2c282a941518@bootlin.com> References: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> In-Reply-To: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> To: Florian Fainelli , Broadcom internal kernel review list , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Radu Pirea , Jay Vosburgh , Andy Gospodarek , Nicolas Ferre , Claudiu Beznea , Willem de Bruijn , Jonathan Corbet , Horatiu Vultur , UNGLinuxDriver@microchip.com, Simon Horman , Vladimir Oltean , donald.hunter@gmail.com, danieller@nvidia.com, ecree.xilinx@gmail.com, Andrew Lunn Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-doc@vger.kernel.org, Maxime Chevallier , Rahul Rameshbabu , Willem de Bruijn , Shannon Nelson , Alexandra Winter , Kory Maincent X-Mailer: b4 0.14.1 X-GND-Sasl: kory.maincent@bootlin.com Introduce the description of a hwtstamp provider, mainly defined with a the hwtstamp source and the phydev pointer. Add a hwtstamp provider description within the netdev structure to allow saving the hwtstamp we want to use. This prepares for future support of an ethtool netlink command to select the desired hwtstamp provider. By default, the old API that does not support hwtstamp selectability is used, meaning the hwtstamp provider pointer is unset. Signed-off-by: Kory Maincent Tested-by: Claudiu Beznea --- Change in v8: - New patch Change in v10: - Set hwtstamp in netdevice as a pointer for future use of rcu lock. - Fix a nit in teh order of setting phydev pointer. - Add a missing kdoc description. Change in v13: - Remove an include from netdevices.h. Change in v16: - Import the part of the patch 12 which belong to the hwtstamp provider selectability of net core. Change in v18: - Fix a doc NIT. Change in v20: - Rework the hwtstamp provider design. Use hwtstamp source alongside with phydev pointer instead. --- drivers/net/phy/phy_device.c | 10 ++++++++ include/linux/net_tstamp.h | 29 +++++++++++++++++++++++ include/linux/netdevice.h | 4 ++++ include/uapi/linux/net_tstamp.h | 11 +++++++++ net/core/dev_ioctl.c | 41 ++++++++++++++++++++++++++++++-- net/core/timestamping.c | 52 +++++++++++++++++++++++++++++++++++++= ---- 6 files changed, 140 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index b26bb33cd1d4..1a908af4175b 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1998,6 +1999,15 @@ void phy_detach(struct phy_device *phydev) =20 phy_suspend(phydev); if (dev) { + struct hwtstamp_provider *hwprov; + + hwprov =3D rtnl_dereference(dev->hwprov); + /* Disable timestamp if it is the one selected */ + if (hwprov && hwprov->phydev =3D=3D phydev) { + rcu_assign_pointer(dev->hwprov, NULL); + kfree_rcu(hwprov, rcu_head); + } + phydev->attached_dev->phydev =3D NULL; phydev->attached_dev =3D NULL; phy_link_topo_del_phy(dev, phydev); diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h index 662074b08c94..ff0758e88ea1 100644 --- a/include/linux/net_tstamp.h +++ b/include/linux/net_tstamp.h @@ -19,6 +19,33 @@ enum hwtstamp_source { HWTSTAMP_SOURCE_PHYLIB, }; =20 +/** + * struct hwtstamp_provider_desc - hwtstamp provider description + * + * @index: index of the hwtstamp provider. + * @qualifier: hwtstamp provider qualifier. + */ +struct hwtstamp_provider_desc { + int index; + enum hwtstamp_provider_qualifier qualifier; +}; + +/** + * struct hwtstamp_provider - hwtstamp provider object + * + * @rcu_head: RCU callback used to free the struct. + * @source: source of the hwtstamp provider. + * @phydev: pointer of the phydev source in case a PTP coming from phylib + * @desc: hwtstamp provider description. + */ + +struct hwtstamp_provider { + struct rcu_head rcu_head; + enum hwtstamp_source source; + struct phy_device *phydev; + struct hwtstamp_provider_desc desc; +}; + /** * struct kernel_hwtstamp_config - Kernel copy of struct hwtstamp_config * @@ -31,6 +58,7 @@ enum hwtstamp_source { * copied the ioctl request back to user space * @source: indication whether timestamps should come from the netdev or f= rom * an attached phylib PHY + * @qualifier: qualifier of the hwtstamp provider * * Prefer using this structure for in-kernel processing of hardware * timestamping configuration, over the inextensible struct hwtstamp_config @@ -43,6 +71,7 @@ struct kernel_hwtstamp_config { struct ifreq *ifr; bool copied_to_user; enum hwtstamp_source source; + enum hwtstamp_provider_qualifier qualifier; }; =20 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 d917949bba03..2593019ad5b1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -82,6 +82,7 @@ struct xdp_metadata_ops; struct xdp_md; struct ethtool_netdev_state; struct phy_link_topology; +struct hwtstamp_provider; =20 typedef u32 xdp_features_t; =20 @@ -2045,6 +2046,7 @@ enum netdev_reg_state { * * @neighbours: List heads pointing to this device's neighbours' * dev_list, one per address-family. + * @hwprov: Tracks which PTP performs hardware packet time stamping. * * FIXME: cleanup struct net_device such that network protocol info * moves out. @@ -2457,6 +2459,8 @@ struct net_device { =20 struct hlist_head neighbours[NEIGH_NR_TABLES]; =20 + struct hwtstamp_provider __rcu *hwprov; + u8 priv[] ____cacheline_aligned __counted_by(priv_len); } ____cacheline_aligned; diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstam= p.h index 858339d1c1c4..55b0ab51096c 100644 --- a/include/uapi/linux/net_tstamp.h +++ b/include/uapi/linux/net_tstamp.h @@ -13,6 +13,17 @@ #include #include /* for SO_TIMESTAMPING */ =20 +/* + * Possible type of hwtstamp provider. Mainly "precise" the default one + * is for IEEE 1588 quality and "approx" is for NICs DMA point. + */ +enum hwtstamp_provider_qualifier { + HWTSTAMP_PROVIDER_QUALIFIER_PRECISE, + HWTSTAMP_PROVIDER_QUALIFIER_APPROX, + + HWTSTAMP_PROVIDER_QUALIFIER_CNT, +}; + /* SO_TIMESTAMPING flags */ enum { SOF_TIMESTAMPING_TX_HARDWARE =3D (1<<0), diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 1f09930fca26..087a57b7e4fa 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -269,6 +270,21 @@ static int dev_eth_ioctl(struct net_device *dev, int dev_get_hwtstamp_phylib(struct net_device *dev, struct kernel_hwtstamp_config *cfg) { + struct hwtstamp_provider *hwprov; + + hwprov =3D rtnl_dereference(dev->hwprov); + if (hwprov) { + cfg->qualifier =3D hwprov->desc.qualifier; + if (hwprov->source =3D=3D HWTSTAMP_SOURCE_PHYLIB && + hwprov->phydev) + return phy_hwtstamp_get(hwprov->phydev, cfg); + + if (hwprov->source =3D=3D HWTSTAMP_SOURCE_NETDEV) + return dev->netdev_ops->ndo_hwtstamp_get(dev, cfg); + + return -EOPNOTSUPP; + } + if (phy_is_default_hwtstamp(dev->phydev)) return phy_hwtstamp_get(dev->phydev, cfg); =20 @@ -324,11 +340,32 @@ int dev_set_hwtstamp_phylib(struct net_device *dev, struct netlink_ext_ack *extack) { const struct net_device_ops *ops =3D dev->netdev_ops; - bool phy_ts =3D phy_is_default_hwtstamp(dev->phydev); struct kernel_hwtstamp_config old_cfg =3D {}; + struct hwtstamp_provider *hwprov; + struct phy_device *phydev; bool changed =3D false; + bool phy_ts; int err; =20 + hwprov =3D rtnl_dereference(dev->hwprov); + if (hwprov) { + if (hwprov->source =3D=3D HWTSTAMP_SOURCE_PHYLIB && + hwprov->phydev) { + phy_ts =3D true; + phydev =3D hwprov->phydev; + } else if (hwprov->source =3D=3D HWTSTAMP_SOURCE_NETDEV) { + phy_ts =3D false; + } else { + return -EOPNOTSUPP; + } + + cfg->qualifier =3D hwprov->desc.qualifier; + } else { + phy_ts =3D phy_is_default_hwtstamp(dev->phydev); + if (phy_ts) + phydev =3D dev->phydev; + } + cfg->source =3D phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV; =20 if (phy_ts && dev->see_all_hwtstamp_requests) { @@ -350,7 +387,7 @@ int dev_set_hwtstamp_phylib(struct net_device *dev, changed =3D kernel_hwtstamp_config_changed(&old_cfg, cfg); =20 if (phy_ts) { - err =3D phy_hwtstamp_set(dev->phydev, cfg, extack); + err =3D phy_hwtstamp_set(phydev, cfg, extack); if (err) { if (changed) ops->ndo_hwtstamp_set(dev, &old_cfg, NULL); diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 3717fb152ecc..a50a7ef49ae8 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c @@ -9,6 +9,7 @@ #include #include #include +#include =20 static unsigned int classify(const struct sk_buff *skb) { @@ -21,19 +22,39 @@ static unsigned int classify(const struct sk_buff *skb) =20 void skb_clone_tx_timestamp(struct sk_buff *skb) { + struct hwtstamp_provider *hwprov; struct mii_timestamper *mii_ts; + struct phy_device *phydev; struct sk_buff *clone; unsigned int type; =20 - if (!skb->sk || !skb->dev || - !phy_is_default_hwtstamp(skb->dev->phydev)) + if (!skb->sk || !skb->dev) return; =20 + rcu_read_lock(); + hwprov =3D rcu_dereference(skb->dev->hwprov); + if (hwprov) { + if (hwprov->source !=3D HWTSTAMP_SOURCE_PHYLIB || + !hwprov->phydev) { + rcu_read_unlock(); + return; + } + + phydev =3D hwprov->phydev; + } else { + phydev =3D skb->dev->phydev; + if (!phy_is_default_hwtstamp(phydev)) { + rcu_read_unlock(); + return; + } + } + rcu_read_unlock(); + type =3D classify(skb); if (type =3D=3D PTP_CLASS_NONE) return; =20 - mii_ts =3D skb->dev->phydev->mii_ts; + mii_ts =3D phydev->mii_ts; if (likely(mii_ts->txtstamp)) { clone =3D skb_clone_sk(skb); if (!clone) @@ -45,12 +66,33 @@ EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); =20 bool skb_defer_rx_timestamp(struct sk_buff *skb) { + struct hwtstamp_provider *hwprov; struct mii_timestamper *mii_ts; + struct phy_device *phydev; unsigned int type; =20 - if (!skb->dev || !phy_is_default_hwtstamp(skb->dev->phydev)) + if (!skb->dev) return false; =20 + rcu_read_lock(); + hwprov =3D rcu_dereference(skb->dev->hwprov); + if (hwprov) { + if (hwprov->source !=3D HWTSTAMP_SOURCE_PHYLIB || + !hwprov->phydev) { + rcu_read_unlock(); + return false; + } + + phydev =3D hwprov->phydev; + } else { + phydev =3D skb->dev->phydev; + if (!phy_is_default_hwtstamp(phydev)) { + rcu_read_unlock(); + return false; + } + } + rcu_read_unlock(); + if (skb_headroom(skb) < ETH_HLEN) return false; =20 @@ -63,7 +105,7 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb) if (type =3D=3D PTP_CLASS_NONE) return false; =20 - mii_ts =3D skb->dev->phydev->mii_ts; + mii_ts =3D phydev->mii_ts; if (likely(mii_ts->rxtstamp)) return mii_ts->rxtstamp(mii_ts, skb, type); =20 --=20 2.34.1 From nobody Sun Dec 14 19:14:01 2025 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA61E22968B; Thu, 12 Dec 2024 17:07:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023236; cv=none; b=jChvzJEqjEzU4WYrBDrpIPUU7uJUqvu+TSNZ42stcUaMBH0Hoz2dTfhsRVk8h1QE/6sG7XqqdukLGGWB1mU0oZywGdh+bXlQuSN0OhHPKsHYyLEeV6xfS0INehJPmVz1oH001QfYtSJHLnCW7i87GYlpFFt2/hwGONWYpJJGPlU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023236; c=relaxed/simple; bh=+zS7ZopVb60N/+KR1n1X1p9bxqSjBRGrYh3W3wePV8s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FpHuFURSpHCP47z0xFjvGqVzU5dl9aR6/Uo04kxTVv0iSrShQ+HZoOcLqInnRPMgd6dJRXdBaAAx+hLoGKOudLrjpjJVR9CPEJHn5j1YsXTKKeT/vybToRXrkw2nsYsU971dquoqp8xX2ZL1ZdPm4E31lx4pz/AS9tVWHdHQ/5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=NS0mL0hu; arc=none smtp.client-ip=217.70.183.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="NS0mL0hu" Received: by mail.gandi.net (Postfix) with ESMTPSA id 57B9760004; Thu, 12 Dec 2024 17:07:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734023232; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Dy4ERvvpz1XqYtJgbnaeC/A15WSsIHKjcL2qS8gf7hA=; b=NS0mL0hu1SxZlXvQgpELIcJ087KPER42FW8FyGAe2O5RW3eXAhP6tJ8pp2EjSeuO6WS5wx a42svIfy3UZPWA6Bg6oEYYZY+Eqn1BXizCWI2XnJnIEVIaX0iyHNMC9zpt26g9vN08EdNT 7WRY7TQmYWGXGtqVWkj3JX2drh9RoW46zGKjlG02cSY9gJmKBbTWPXiD6ybutLwQQsg7d3 Vses+SCJHr6QomjSuWanJnByStl03uHH223NVnZex4F3HyaRrMOqLc5aih+LVbqI7HZ1i1 xw8wXDuVsJbF4ED6P1C5BAnXaxM/hAc4egCsKDJHZ0mrEwvTaz+kfxw99LaVEQ== From: Kory Maincent Date: Thu, 12 Dec 2024 18:06:44 +0100 Subject: [PATCH net-next v21 4/5] net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241212-feature_ptp_netnext-v21-4-2c282a941518@bootlin.com> References: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> In-Reply-To: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> To: Florian Fainelli , Broadcom internal kernel review list , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Radu Pirea , Jay Vosburgh , Andy Gospodarek , Nicolas Ferre , Claudiu Beznea , Willem de Bruijn , Jonathan Corbet , Horatiu Vultur , UNGLinuxDriver@microchip.com, Simon Horman , Vladimir Oltean , donald.hunter@gmail.com, danieller@nvidia.com, ecree.xilinx@gmail.com, Andrew Lunn Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-doc@vger.kernel.org, Maxime Chevallier , Rahul Rameshbabu , Willem de Bruijn , Shannon Nelson , Alexandra Winter , Kory Maincent X-Mailer: b4 0.14.1 X-GND-Sasl: kory.maincent@bootlin.com Either the MAC or the PHY can provide hwtstamp, so we should be able to read the tsinfo for any hwtstamp provider. Enhance 'get' command to retrieve tsinfo of hwtstamp providers within a network topology. Add support for a specific dump command to retrieve all hwtstamp providers within the network topology, with added functionality for filtered dump to target a single interface. Signed-off-by: Kory Maincent --- Change in v8: - New patch Change in v9: - Fix nit in done callback. Change in v10: - Add documentation. - Add extack error messages. - Add NLA_POLICY_* checks. - Fix few nits. - Add ETHTOOL_A_TSINFO_GHWTSTAMP netlink attributes instead of a bit in ETHTOOL_A_TSINFO_TIMESTAMPING bitset. - Add tsinfo_parse_hwtstamp_provider function for more readability. - Move netdev_support_hwtstamp_qualifier function in core ptp instead of core net. - Add refcount put to release the ptp object. - Use rcu lock to avoid memory leak. Change in v12: - Add missing return description in the kdoc. - Fix possible leak due to uninitialised variable. - Add a missing static. Change in v13: - Remove useless EXPORT_SYMBOL(). - Fix issues reported by sparse and smatch. - Fix issues when building PTP as a module. - Rename HWTSTAMP_PROVIDER_NEST to HWTSTAMP_PROVIDER. Change in v16: - Used call_rcu() instead of synchronize_rcu() to free the hwtstamp_provider struct. - Fix documentation typo. - Fix few nit. - Fix possible issue regardings stats. - Remove hwtstamp config get and set from tsinfo. Change in v20: - Rethink the hwtstamp provider design implementation. - Remove the "user" pointer from the PTP structure. --- Documentation/netlink/specs/ethtool.yaml | 20 ++ Documentation/networking/ethtool-netlink.rst | 7 +- include/linux/ethtool.h | 4 + include/uapi/linux/ethtool_netlink_generated.h | 10 + net/ethtool/common.c | 141 +++++++++- net/ethtool/common.h | 13 + net/ethtool/netlink.c | 6 +- net/ethtool/netlink.h | 5 +- net/ethtool/ts.h | 20 ++ net/ethtool/tsinfo.c | 358 +++++++++++++++++++++= +++- 10 files changed, 563 insertions(+), 21 deletions(-) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netli= nk/specs/ethtool.yaml index c7634e957d9c..4082816e5f3d 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -836,6 +836,20 @@ attribute-sets: - name: tx-err type: uint + - + name: ts-hwtstamp-provider + attr-cnt-name: __ethtool-a-ts-hwtstamp-provider-cnt + attributes: + - + name: unspec + type: unused + value: 0 + - + name: index + type: u32 + - + name: qualifier + type: u32 - name: tsinfo attr-cnt-name: __ethtool-a-tsinfo-cnt @@ -867,6 +881,10 @@ attribute-sets: name: stats type: nest nested-attributes: ts-stat + - + name: hwtstamp-provider + type: nest + nested-attributes: ts-hwtstamp-provider - name: cable-result attr-cnt-name: __ethtool-a-cable-result-cnt @@ -1912,6 +1930,7 @@ operations: request: attributes: - header + - hwtstamp-provider reply: attributes: - header @@ -1920,6 +1939,7 @@ operations: - rx-filters - phc-index - stats + - hwtstamp-provider dump: *tsinfo-get-op - name: cable-test-act diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/n= etworking/ethtool-netlink.rst index b25926071ece..c585e2f0ddfa 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -1245,9 +1245,10 @@ Gets timestamping information like ``ETHTOOL_GET_TS_= INFO`` ioctl request. =20 Request contents: =20 - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - ``ETHTOOL_A_TSINFO_HEADER`` nested request header - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + ``ETHTOOL_A_TSINFO_HEADER`` nested request header + ``ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER`` nested PTP hw clock provider + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D =20 Kernel response contents: =20 diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index e217c6321ed0..f711bfd75c4d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -711,6 +711,7 @@ struct ethtool_rxfh_param { * @cmd: command number =3D %ETHTOOL_GET_TS_INFO * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING = flags * @phc_index: device index of the associated PHC, or -1 if there is none + * @phc_qualifier: qualifier of the associated PHC * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration valu= es * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration = values */ @@ -718,6 +719,7 @@ struct kernel_ethtool_ts_info { u32 cmd; u32 so_timestamping; int phc_index; + enum hwtstamp_provider_qualifier phc_qualifier; enum hwtstamp_tx_types tx_types; enum hwtstamp_rx_filters rx_filters; }; @@ -749,6 +751,7 @@ struct kernel_ethtool_ts_info { * @rss_context argument to @create_rxfh_context and friends. * @supported_coalesce_params: supported types of interrupt coalescing. * @supported_ring_params: supported ring params. + * @supported_hwtstamp_qualifiers: bitfield of supported hwtstamp qualifie= r. * @get_drvinfo: Report driver/device information. Modern drivers no * longer have to implement this callback. Most fields are * correctly filled in by the core using system information, or @@ -966,6 +969,7 @@ struct ethtool_ops { u32 rxfh_max_num_contexts; u32 supported_coalesce_params; u32 supported_ring_params; + u32 supported_hwtstamp_qualifiers; void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); int (*get_regs_len)(struct net_device *); void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); diff --git a/include/uapi/linux/ethtool_netlink_generated.h b/include/uapi/= linux/ethtool_netlink_generated.h index b58f352fe4f2..df289dde0f61 100644 --- a/include/uapi/linux/ethtool_netlink_generated.h +++ b/include/uapi/linux/ethtool_netlink_generated.h @@ -385,6 +385,15 @@ enum { ETHTOOL_A_TS_STAT_MAX =3D (__ETHTOOL_A_TS_STAT_CNT - 1) }; =20 +enum { + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_UNSPEC, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER, + + __ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX =3D (__ETHTOOL_A_TS_HWTSTAMP_PROVIDER_= CNT - 1) +}; + enum { ETHTOOL_A_TSINFO_UNSPEC, ETHTOOL_A_TSINFO_HEADER, @@ -393,6 +402,7 @@ enum { ETHTOOL_A_TSINFO_RX_FILTERS, ETHTOOL_A_TSINFO_PHC_INDEX, ETHTOOL_A_TSINFO_STATS, + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER, =20 __ETHTOOL_A_TSINFO_CNT, ETHTOOL_A_TSINFO_MAX =3D (__ETHTOOL_A_TSINFO_CNT - 1) diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 05ce4f8080b3..666db40bcfda 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -5,9 +5,12 @@ #include #include #include +#include =20 #include "netlink.h" #include "common.h" +#include "../core/dev.h" + =20 const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = =3D { [NETIF_F_SG_BIT] =3D "tx-scatter-gather", @@ -763,20 +766,91 @@ int ethtool_check_ops(const struct ethtool_ops *ops) return 0; } =20 -int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts= _info *info) +static void ethtool_init_tsinfo(struct kernel_ethtool_ts_info *info) { - const struct ethtool_ops *ops =3D dev->ethtool_ops; - struct phy_device *phydev =3D dev->phydev; - int err =3D 0; - memset(info, 0, sizeof(*info)); info->cmd =3D ETHTOOL_GET_TS_INFO; info->phc_index =3D -1; +} + +int ethtool_net_get_ts_info_by_phc(struct net_device *dev, + struct kernel_ethtool_ts_info *info, + struct hwtstamp_provider_desc *hwprov_desc) +{ + const struct ethtool_ops *ops =3D dev->ethtool_ops; + int err; + + if (!ops->get_ts_info) + return -ENODEV; + + /* Does ptp comes from netdev */ + ethtool_init_tsinfo(info); + info->phc_qualifier =3D hwprov_desc->qualifier; + err =3D ops->get_ts_info(dev, info); + if (err) + return err; + + if (info->phc_index =3D=3D hwprov_desc->index && + net_support_hwtstamp_qualifier(dev, hwprov_desc->qualifier)) + return 0; + + return -ENODEV; +} + +int +ethtool_phy_get_ts_info_by_phc(struct net_device *dev, + struct kernel_ethtool_ts_info *info, + struct hwtstamp_provider_desc *hwprov_desc) +{ + int err; + + /* Only precise qualifier is supported in phydev */ + if (hwprov_desc->qualifier !=3D HWTSTAMP_PROVIDER_QUALIFIER_PRECISE) + return -ENODEV; + + /* Look in the phy topology */ + if (dev->link_topo) { + struct phy_device_node *pdn; + unsigned long phy_index; + + xa_for_each(&dev->link_topo->phys, phy_index, pdn) { + if (!phy_has_tsinfo(pdn->phy)) + continue; + + ethtool_init_tsinfo(info); + err =3D phy_ts_info(pdn->phy, info); + if (err) + return err; + + if (info->phc_index =3D=3D hwprov_desc->index) + return 0; + } + return -ENODEV; + } + + /* Look on the dev->phydev */ + if (phy_has_tsinfo(dev->phydev)) { + ethtool_init_tsinfo(info); + err =3D phy_ts_info(dev->phydev, info); + if (err) + return err; + + if (info->phc_index =3D=3D hwprov_desc->index) + return 0; + } + + return -ENODEV; +} + +int ethtool_get_ts_info_by_phc(struct net_device *dev, + struct kernel_ethtool_ts_info *info, + struct hwtstamp_provider_desc *hwprov_desc) +{ + int err; =20 - if (phy_is_default_hwtstamp(phydev) && phy_has_tsinfo(phydev)) - err =3D phy_ts_info(phydev, info); - else if (ops->get_ts_info) - err =3D ops->get_ts_info(dev, info); + err =3D ethtool_net_get_ts_info_by_phc(dev, info, hwprov_desc); + if (err =3D=3D -ENODEV) + err =3D ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc); =20 info->so_timestamping |=3D SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; @@ -784,6 +858,55 @@ int __ethtool_get_ts_info(struct net_device *dev, stru= ct kernel_ethtool_ts_info return err; } =20 +int __ethtool_get_ts_info(struct net_device *dev, + struct kernel_ethtool_ts_info *info) +{ + struct hwtstamp_provider *hwprov; + + hwprov =3D rtnl_dereference(dev->hwprov); + /* No provider specified, use default behavior */ + if (!hwprov) { + const struct ethtool_ops *ops =3D dev->ethtool_ops; + struct phy_device *phydev =3D dev->phydev; + int err =3D 0; + + ethtool_init_tsinfo(info); + if (phy_is_default_hwtstamp(phydev) && + phy_has_tsinfo(phydev)) + err =3D phy_ts_info(phydev, info); + else if (ops->get_ts_info) + err =3D ops->get_ts_info(dev, info); + + info->so_timestamping |=3D SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + + return err; + } + + return ethtool_get_ts_info_by_phc(dev, info, &hwprov->desc); +} + +bool net_support_hwtstamp_qualifier(struct net_device *dev, + enum hwtstamp_provider_qualifier qualifier) +{ + const struct ethtool_ops *ops =3D dev->ethtool_ops; + + if (!ops) + return false; + + /* Return true with precise qualifier and with NIC without + * qualifier description to not break the old behavior. + */ + if (!ops->supported_hwtstamp_qualifiers && + qualifier =3D=3D HWTSTAMP_PROVIDER_QUALIFIER_PRECISE) + return true; + + if (ops->supported_hwtstamp_qualifiers & BIT(qualifier)) + return true; + + return false; +} + int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index) { struct kernel_ethtool_ts_info info =3D { }; diff --git a/net/ethtool/common.h b/net/ethtool/common.h index 4a2de3ce7354..f5119204c8ff 100644 --- a/net/ethtool/common.h +++ b/net/ethtool/common.h @@ -21,6 +21,7 @@ struct link_mode_info { }; =20 struct genl_info; +struct hwtstamp_provider_desc; =20 extern const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]; @@ -49,6 +50,18 @@ int ethtool_check_max_channel(struct net_device *dev, struct genl_info *info); int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context); int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts= _info *info); +int ethtool_get_ts_info_by_phc(struct net_device *dev, + struct kernel_ethtool_ts_info *info, + struct hwtstamp_provider_desc *hwprov_desc); +int ethtool_net_get_ts_info_by_phc(struct net_device *dev, + struct kernel_ethtool_ts_info *info, + struct hwtstamp_provider_desc *hwprov_desc); +int +ethtool_phy_get_ts_info_by_phc(struct net_device *dev, + struct kernel_ethtool_ts_info *info, + struct hwtstamp_provider_desc *hwprov_desc); +bool net_support_hwtstamp_qualifier(struct net_device *dev, + enum hwtstamp_provider_qualifier qualifier); =20 extern const struct ethtool_phy_ops *ethtool_phy_ops; extern const struct ethtool_pse_ops *ethtool_pse_ops; diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index e3f0ef6b851b..6ae1d91f36e7 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -1074,9 +1074,9 @@ static const struct genl_ops ethtool_genl_ops[] =3D { { .cmd =3D ETHTOOL_MSG_TSINFO_GET, .doit =3D ethnl_default_doit, - .start =3D ethnl_default_start, - .dumpit =3D ethnl_default_dumpit, - .done =3D ethnl_default_done, + .start =3D ethnl_tsinfo_start, + .dumpit =3D ethnl_tsinfo_dumpit, + .done =3D ethnl_tsinfo_done, .policy =3D ethnl_tsinfo_get_policy, .maxattr =3D ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1, }, diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 203b08eb6c6f..960cda13e4fc 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -464,7 +464,7 @@ extern const struct nla_policy ethnl_pause_get_policy[E= THTOOL_A_PAUSE_STATS_SRC extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX += 1]; extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER += 1]; extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_T= IMER + 1]; -extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HE= ADER + 1]; +extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_MA= X + 1]; extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE= _TEST_HEADER + 1]; extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_C= ABLE_TEST_TDR_CFG + 1]; extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNN= EL_INFO_HEADER + 1]; @@ -499,6 +499,9 @@ int ethnl_phy_start(struct netlink_callback *cb); int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info); int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int ethnl_phy_done(struct netlink_callback *cb); +int ethnl_tsinfo_start(struct netlink_callback *cb); +int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb); +int ethnl_tsinfo_done(struct netlink_callback *cb); =20 extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_G= STRING_LEN]; diff --git a/net/ethtool/ts.h b/net/ethtool/ts.h new file mode 100644 index 000000000000..d901a879a671 --- /dev/null +++ b/net/ethtool/ts.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _NET_ETHTOOL_TS_H +#define _NET_ETHTOOL_TS_H + +#include "netlink.h" + +static const struct nla_policy +ethnl_ts_hwtst_prov_policy[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX + 1] =3D { + [ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX] =3D { .type =3D NLA_U32 }, + [ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER] =3D + NLA_POLICY_MAX(NLA_U32, HWTSTAMP_PROVIDER_QUALIFIER_CNT - 1) +}; + +int ts_parse_hwtst_provider(const struct nlattr *nest, + struct hwtstamp_provider_desc *hwprov_desc, + struct netlink_ext_ack *extack, + bool *mod); + +#endif /* _NET_ETHTOOL_TS_H */ diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c index 03d12d6f79ca..7e495a41aeec 100644 --- a/net/ethtool/tsinfo.c +++ b/net/ethtool/tsinfo.c @@ -1,13 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-only =20 #include +#include +#include +#include =20 #include "netlink.h" #include "common.h" #include "bitset.h" +#include "ts.h" =20 struct tsinfo_req_info { struct ethnl_req_info base; + struct hwtstamp_provider_desc hwprov_desc; }; =20 struct tsinfo_reply_data { @@ -16,34 +21,96 @@ struct tsinfo_reply_data { struct ethtool_ts_stats stats; }; =20 +#define TSINFO_REQINFO(__req_base) \ + container_of(__req_base, struct tsinfo_req_info, base) + #define TSINFO_REPDATA(__reply_base) \ container_of(__reply_base, struct tsinfo_reply_data, base) =20 #define ETHTOOL_TS_STAT_CNT \ (__ETHTOOL_A_TS_STAT_CNT - (ETHTOOL_A_TS_STAT_UNSPEC + 1)) =20 -const struct nla_policy ethnl_tsinfo_get_policy[] =3D { +const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1] = =3D { [ETHTOOL_A_TSINFO_HEADER] =3D NLA_POLICY_NESTED(ethnl_header_policy_stats), + [ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER] =3D + NLA_POLICY_NESTED(ethnl_ts_hwtst_prov_policy), }; =20 +int ts_parse_hwtst_provider(const struct nlattr *nest, + struct hwtstamp_provider_desc *hwprov_desc, + struct netlink_ext_ack *extack, + bool *mod) +{ + struct nlattr *tb[ARRAY_SIZE(ethnl_ts_hwtst_prov_policy)]; + int ret; + + ret =3D nla_parse_nested(tb, + ARRAY_SIZE(ethnl_ts_hwtst_prov_policy) - 1, + nest, + ethnl_ts_hwtst_prov_policy, extack); + if (ret < 0) + return ret; + + if (NL_REQ_ATTR_CHECK(extack, nest, tb, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX) || + NL_REQ_ATTR_CHECK(extack, nest, tb, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER)) + return -EINVAL; + + ethnl_update_u32(&hwprov_desc->index, + tb[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX], + mod); + ethnl_update_u32(&hwprov_desc->qualifier, + tb[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER], + mod); + + return 0; +} + +static int +tsinfo_parse_request(struct ethnl_req_info *req_base, struct nlattr **tb, + struct netlink_ext_ack *extack) +{ + struct tsinfo_req_info *req =3D TSINFO_REQINFO(req_base); + bool mod =3D false; + + req->hwprov_desc.index =3D -1; + + if (!tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER]) + return 0; + + return ts_parse_hwtst_provider(tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER], + &req->hwprov_desc, extack, &mod); +} + static int tsinfo_prepare_data(const struct ethnl_req_info *req_base, struct ethnl_reply_data *reply_base, const struct genl_info *info) { struct tsinfo_reply_data *data =3D TSINFO_REPDATA(reply_base); + struct tsinfo_req_info *req =3D TSINFO_REQINFO(req_base); struct net_device *dev =3D reply_base->dev; int ret; =20 ret =3D ethnl_ops_begin(dev); if (ret < 0) return ret; + + if (req->hwprov_desc.index !=3D -1) { + ret =3D ethtool_get_ts_info_by_phc(dev, &data->ts_info, + &req->hwprov_desc); + ethnl_ops_complete(dev); + return ret; + } + if (req_base->flags & ETHTOOL_FLAG_STATS) { ethtool_stats_init((u64 *)&data->stats, sizeof(data->stats) / sizeof(u64)); if (dev->ethtool_ops->get_ts_stats) dev->ethtool_ops->get_ts_stats(dev, &data->stats); } + ret =3D __ethtool_get_ts_info(dev, &data->ts_info); ethnl_ops_complete(dev); =20 @@ -87,8 +154,11 @@ static int tsinfo_reply_size(const struct ethnl_req_inf= o *req_base, return ret; len +=3D ret; /* _TSINFO_RX_FILTERS */ } - if (ts_info->phc_index >=3D 0) + if (ts_info->phc_index >=3D 0) { len +=3D nla_total_size(sizeof(u32)); /* _TSINFO_PHC_INDEX */ + /* _TSINFO_HWTSTAMP_PROVIDER */ + len +=3D nla_total_size(0) + 2 * nla_total_size(sizeof(u32)); + } if (req_base->flags & ETHTOOL_FLAG_STATS) len +=3D nla_total_size(0) + /* _TSINFO_STATS */ nla_total_size_64bit(sizeof(u64)) * ETHTOOL_TS_STAT_CNT; @@ -163,9 +233,29 @@ static int tsinfo_fill_reply(struct sk_buff *skb, if (ret < 0) return ret; } - if (ts_info->phc_index >=3D 0 && - nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, ts_info->phc_index)) - return -EMSGSIZE; + if (ts_info->phc_index >=3D 0) { + struct nlattr *nest; + + ret =3D nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, + ts_info->phc_index); + if (ret) + return -EMSGSIZE; + + nest =3D nla_nest_start(skb, ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER); + if (!nest) + return -EMSGSIZE; + + if (nla_put_u32(skb, ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX, + ts_info->phc_index) || + nla_put_u32(skb, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER, + ts_info->phc_qualifier)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + + nla_nest_end(skb, nest); + } if (req_base->flags & ETHTOOL_FLAG_STATS && tsinfo_put_stats(skb, &data->stats)) return -EMSGSIZE; @@ -173,6 +263,263 @@ static int tsinfo_fill_reply(struct sk_buff *skb, return 0; } =20 +struct ethnl_tsinfo_dump_ctx { + struct tsinfo_req_info *req_info; + struct tsinfo_reply_data *reply_data; + unsigned long pos_ifindex; + bool netdev_dump_done; + unsigned long pos_phyindex; + enum hwtstamp_provider_qualifier pos_phcqualifier; +}; + +static void *ethnl_tsinfo_prepare_dump(struct sk_buff *skb, + struct net_device *dev, + struct tsinfo_reply_data *reply_data, + struct netlink_callback *cb) +{ + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + void *ehdr =3D NULL; + + ehdr =3D ethnl_dump_put(skb, cb, + ETHTOOL_MSG_TSINFO_GET_REPLY); + if (!ehdr) + return ERR_PTR(-EMSGSIZE); + + reply_data =3D ctx->reply_data; + memset(reply_data, 0, sizeof(*reply_data)); + reply_data->base.dev =3D dev; + memset(&reply_data->ts_info, 0, sizeof(reply_data->ts_info)); + + return ehdr; +} + +static int ethnl_tsinfo_end_dump(struct sk_buff *skb, + struct net_device *dev, + struct tsinfo_req_info *req_info, + struct tsinfo_reply_data *reply_data, + void *ehdr) +{ + int ret; + + reply_data->ts_info.so_timestamping |=3D SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + + ret =3D ethnl_fill_reply_header(skb, dev, ETHTOOL_A_TSINFO_HEADER); + if (ret < 0) + return ret; + + ret =3D tsinfo_fill_reply(skb, &req_info->base, &reply_data->base); + if (ret < 0) + return ret; + + reply_data->base.dev =3D NULL; + genlmsg_end(skb, ehdr); + + return ret; +} + +static int ethnl_tsinfo_dump_one_phydev(struct sk_buff *skb, + struct net_device *dev, + struct phy_device *phydev, + struct netlink_callback *cb) +{ + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + struct tsinfo_reply_data *reply_data; + struct tsinfo_req_info *req_info; + void *ehdr =3D NULL; + int ret =3D 0; + + if (!phy_has_tsinfo(phydev)) + return -EOPNOTSUPP; + + reply_data =3D ctx->reply_data; + req_info =3D ctx->req_info; + ehdr =3D ethnl_tsinfo_prepare_dump(skb, dev, reply_data, cb); + if (IS_ERR(ehdr)) + return PTR_ERR(ehdr); + + ret =3D phy_ts_info(phydev, &reply_data->ts_info); + if (ret < 0) + goto err; + + ret =3D ethnl_tsinfo_end_dump(skb, dev, req_info, reply_data, ehdr); + if (ret < 0) + goto err; + + return ret; +err: + genlmsg_cancel(skb, ehdr); + return ret; +} + +static int ethnl_tsinfo_dump_one_netdev(struct sk_buff *skb, + struct net_device *dev, + struct netlink_callback *cb) +{ + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + const struct ethtool_ops *ops =3D dev->ethtool_ops; + struct tsinfo_reply_data *reply_data; + struct tsinfo_req_info *req_info; + void *ehdr =3D NULL; + int ret =3D 0; + + if (!ops->get_ts_info) + return -EOPNOTSUPP; + + reply_data =3D ctx->reply_data; + req_info =3D ctx->req_info; + for (; ctx->pos_phcqualifier < HWTSTAMP_PROVIDER_QUALIFIER_CNT; + ctx->pos_phcqualifier++) { + if (!net_support_hwtstamp_qualifier(dev, + ctx->pos_phcqualifier)) + continue; + + ehdr =3D ethnl_tsinfo_prepare_dump(skb, dev, reply_data, cb); + if (IS_ERR(ehdr)) { + ret =3D PTR_ERR(ehdr); + goto err; + } + + reply_data->ts_info.phc_qualifier =3D ctx->pos_phcqualifier; + ret =3D ops->get_ts_info(dev, &reply_data->ts_info); + if (ret < 0) + goto err; + + ret =3D ethnl_tsinfo_end_dump(skb, dev, req_info, reply_data, + ehdr); + if (ret < 0) + goto err; + } + + return ret; + +err: + genlmsg_cancel(skb, ehdr); + return ret; +} + +static int ethnl_tsinfo_dump_one_net_topo(struct sk_buff *skb, + struct net_device *dev, + struct netlink_callback *cb) +{ + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + struct phy_device_node *pdn; + int ret =3D 0; + + if (!ctx->netdev_dump_done) { + ret =3D ethnl_tsinfo_dump_one_netdev(skb, dev, cb); + if (ret < 0 && ret !=3D -EOPNOTSUPP) + return ret; + ctx->netdev_dump_done =3D true; + } + + if (!dev->link_topo) { + if (phy_has_tsinfo(dev->phydev)) { + ret =3D ethnl_tsinfo_dump_one_phydev(skb, dev, + dev->phydev, cb); + if (ret < 0 && ret !=3D -EOPNOTSUPP) + return ret; + } + + return 0; + } + + xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn, + ctx->pos_phyindex) { + if (phy_has_tsinfo(pdn->phy)) { + ret =3D ethnl_tsinfo_dump_one_phydev(skb, dev, + pdn->phy, cb); + if (ret < 0 && ret !=3D -EOPNOTSUPP) + return ret; + } + } + + return ret; +} + +int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + struct net *net =3D sock_net(skb->sk); + struct net_device *dev; + int ret =3D 0; + + rtnl_lock(); + if (ctx->req_info->base.dev) { + ret =3D ethnl_tsinfo_dump_one_net_topo(skb, + ctx->req_info->base.dev, + cb); + } else { + for_each_netdev_dump(net, dev, ctx->pos_ifindex) { + ret =3D ethnl_tsinfo_dump_one_net_topo(skb, dev, cb); + if (ret < 0 && ret !=3D -EOPNOTSUPP) + break; + ctx->pos_phyindex =3D 0; + ctx->netdev_dump_done =3D false; + ctx->pos_phcqualifier =3D HWTSTAMP_PROVIDER_QUALIFIER_PRECISE; + } + } + rtnl_unlock(); + + return ret; +} + +int ethnl_tsinfo_start(struct netlink_callback *cb) +{ + const struct genl_dumpit_info *info =3D genl_dumpit_info(cb); + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + struct nlattr **tb =3D info->info.attrs; + struct tsinfo_reply_data *reply_data; + struct tsinfo_req_info *req_info; + int ret; + + BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); + + req_info =3D kzalloc(sizeof(*req_info), GFP_KERNEL); + if (!req_info) + return -ENOMEM; + reply_data =3D kzalloc(sizeof(*reply_data), GFP_KERNEL); + if (!reply_data) { + ret =3D -ENOMEM; + goto free_req_info; + } + + ret =3D ethnl_parse_header_dev_get(&req_info->base, + tb[ETHTOOL_A_TSINFO_HEADER], + sock_net(cb->skb->sk), cb->extack, + false); + if (ret < 0) + goto free_reply_data; + + ctx->req_info =3D req_info; + ctx->reply_data =3D reply_data; + ctx->pos_ifindex =3D 0; + ctx->pos_phyindex =3D 0; + ctx->netdev_dump_done =3D false; + ctx->pos_phcqualifier =3D HWTSTAMP_PROVIDER_QUALIFIER_PRECISE; + + return 0; + +free_reply_data: + kfree(reply_data); +free_req_info: + kfree(req_info); + + return ret; +} + +int ethnl_tsinfo_done(struct netlink_callback *cb) +{ + struct ethnl_tsinfo_dump_ctx *ctx =3D (void *)cb->ctx; + struct tsinfo_req_info *req_info =3D ctx->req_info; + + ethnl_parse_header_dev_put(&req_info->base); + kfree(ctx->reply_data); + kfree(ctx->req_info); + + return 0; +} + const struct ethnl_request_ops ethnl_tsinfo_request_ops =3D { .request_cmd =3D ETHTOOL_MSG_TSINFO_GET, .reply_cmd =3D ETHTOOL_MSG_TSINFO_GET_REPLY, @@ -180,6 +527,7 @@ const struct ethnl_request_ops ethnl_tsinfo_request_ops= =3D { .req_info_size =3D sizeof(struct tsinfo_req_info), .reply_data_size =3D sizeof(struct tsinfo_reply_data), =20 + .parse_request =3D tsinfo_parse_request, .prepare_data =3D tsinfo_prepare_data, .reply_size =3D tsinfo_reply_size, .fill_reply =3D tsinfo_fill_reply, --=20 2.34.1 From nobody Sun Dec 14 19:14:01 2025 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D6F822A818; Thu, 12 Dec 2024 17:07:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023241; cv=none; b=ShZxOkrivi0tI5X9MVwlJpWx1SMY7gTnN5aPoIvr9FoYhM9aHXT7xdlIGDONcDvZcZ79mZICMVo4P2VLo9Qpe+xfDFRHHmJXEa2MjUNfw+gVOk2wwIZiJh8woz2w0PrHKFHFYG+163Ez9ANB8J9r52YnbnW6Iset5WE1SJZFns4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734023241; c=relaxed/simple; bh=CHXVKSKn/IxZh2vLp+93+KcyG4ae6bo445pbuVEhkqk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p57tWbgFHUkuHAdUaOXjpzpZnlIydg/c1hdbbHVfldj0xKdx4wKQX9cdiU70rbe04v+tf66iH0B93FxAasRB9Ql2sZZ2Jek0jCGCciEkGMeoRzWyhzWAP5ppIH08+nec9R6xXLdXprO9S68EGpL0NTHoRmEER+xkdmGbqoOH5QU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=YhmXutG6; arc=none smtp.client-ip=217.70.183.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="YhmXutG6" Received: by mail.gandi.net (Postfix) with ESMTPSA id 4C75660007; Thu, 12 Dec 2024 17:07:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734023236; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CaEsv/+oDczqLcPluKLa1EVkmGnGBNKb0UN9mIdjfII=; b=YhmXutG6FYI6/X2UfD6kgVjkOiCxaYhCF7+LrBOfnQYmvGLniWmAtlnkApsVFKswNek+jn bfh7MuX5iH+F0LK1MyDdSFlyyhaaMhqRn24um/UDEGTsR64AbIilLPNcXC1npOPwwKdG4u INzNHGDJ+s6m9nExppeyTaUsoIBipiEw4HXmu19s43ITZV6Jj4izNOSxZqR//uWIkSyh2l bkfUfzZ8a2+KtvJ1NR5IycL63jUJOUlUsojz+WmbbR9gjPacoXZLyy76woDw5fv3G2ddJB lVnqWLzhT5Bu52EqPtD7nkiNQUhxCBh4SPa/SJV5FJkfK+eqQ0LcEsGj79xPOg== From: Kory Maincent Date: Thu, 12 Dec 2024 18:06:45 +0100 Subject: [PATCH net-next v21 5/5] net: ethtool: Add support for tsconfig command to get/set hwtstamp config Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241212-feature_ptp_netnext-v21-5-2c282a941518@bootlin.com> References: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> In-Reply-To: <20241212-feature_ptp_netnext-v21-0-2c282a941518@bootlin.com> To: Florian Fainelli , Broadcom internal kernel review list , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Radu Pirea , Jay Vosburgh , Andy Gospodarek , Nicolas Ferre , Claudiu Beznea , Willem de Bruijn , Jonathan Corbet , Horatiu Vultur , UNGLinuxDriver@microchip.com, Simon Horman , Vladimir Oltean , donald.hunter@gmail.com, danieller@nvidia.com, ecree.xilinx@gmail.com, Andrew Lunn Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-doc@vger.kernel.org, Maxime Chevallier , Rahul Rameshbabu , Willem de Bruijn , Shannon Nelson , Alexandra Winter , Kory Maincent X-Mailer: b4 0.14.1 X-GND-Sasl: kory.maincent@bootlin.com Introduce support for ETHTOOL_MSG_TSCONFIG_GET/SET ethtool netlink socket to read and configure hwtstamp configuration of a PHC provider. Note that simultaneous hwtstamp isn't supported; configuring a new one disables the previous setting. Signed-off-by: Kory Maincent --- Jacob I removed your Reviewed-by as there is few changes on this patch. Changes in v16: - Add a new patch to separate tsinfo into a new tsconfig command to get and set the hwtstamp config. Changes in v17: - Fix a doc misalignment. Changes in v18: - Few changes in the set command - Add a set-reply ethtool socket - Add missing tsconfig netlink the documentation Changes in v20: - Design of hwtstamp provider change. - Remove netlink notification as set_reply is doing the same job. Changes in v21: - NIT change to use ts_hwtst_prov_policy instead of NLA_NESTED. --- Documentation/netlink/specs/ethtool.yaml | 56 ++++ Documentation/networking/ethtool-netlink.rst | 75 +++++ Documentation/networking/timestamping.rst | 38 ++- include/uapi/linux/ethtool_netlink_generated.h | 16 + net/ethtool/Makefile | 2 +- net/ethtool/common.c | 27 +- net/ethtool/common.h | 2 +- net/ethtool/netlink.c | 18 + net/ethtool/netlink.h | 3 + net/ethtool/tsconfig.c | 444 +++++++++++++++++++++= ++++ 10 files changed, 655 insertions(+), 26 deletions(-) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netli= nk/specs/ethtool.yaml index 4082816e5f3d..60f85fbf4156 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -1489,6 +1489,33 @@ attribute-sets: - name: downstream-sfp-name type: string + - + name: tsconfig + attr-cnt-name: __ethtool-a-tsconfig-cnt + attributes: + - + name: unspec + type: unused + value: 0 + - + name: header + type: nest + nested-attributes: header + - + name: hwtstamp-provider + type: nest + nested-attributes: ts-hwtstamp-provider + - + name: tx-types + type: nest + nested-attributes: bitset + - + name: rx-filters + type: nest + nested-attributes: bitset + - + name: hwtstamp-flags + type: u32 =20 operations: enum-model: directional @@ -2314,3 +2341,32 @@ operations: name: phy-ntf doc: Notification for change in PHY devices. notify: phy-get + - + name: tsconfig-get + doc: Get hwtstamp config. + + attribute-set: tsconfig + + do: &tsconfig-get-op + request: + attributes: + - header + reply: + attributes: &tsconfig + - header + - hwtstamp-provider + - tx-types + - rx-filters + - hwtstamp-flags + dump: *tsconfig-get-op + - + name: tsconfig-set + doc: Set hwtstamp config. + + attribute-set: tsconfig + + do: + request: + attributes: *tsconfig + reply: + attributes: *tsconfig diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/n= etworking/ethtool-netlink.rst index c585e2f0ddfa..a7ba6368a4d5 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -237,6 +237,8 @@ Userspace to kernel: ``ETHTOOL_MSG_MM_SET`` set MAC merge layer parameters ``ETHTOOL_MSG_MODULE_FW_FLASH_ACT`` flash transceiver module firmware ``ETHTOOL_MSG_PHY_GET`` get Ethernet PHY information + ``ETHTOOL_MSG_TSCONFIG_GET`` get hw timestamping configuration + ``ETHTOOL_MSG_TSCONFIG_SET`` set hw timestamping configuration =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 Kernel to userspace: @@ -286,6 +288,8 @@ Kernel to userspace: ``ETHTOOL_MSG_MODULE_FW_FLASH_NTF`` transceiver module flash updates ``ETHTOOL_MSG_PHY_GET_REPLY`` Ethernet PHY information ``ETHTOOL_MSG_PHY_NTF`` Ethernet PHY information change + ``ETHTOOL_MSG_TSCONFIG_GET_REPLY`` hw timestamping configuration + ``ETHTOOL_MSG_TSCONFIG_SET_REPLY`` new hw timestamping configurati= on =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 ``GET`` requests are sent by userspace applications to retrieve device @@ -2244,6 +2248,75 @@ Kernel response contents: When ``ETHTOOL_A_PHY_UPSTREAM_TYPE`` is PHY_UPSTREAM_PHY, the PHY's parent= is another PHY. =20 +TSCONFIG_GET +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Retrieves the information about the current hardware timestamping source a= nd +configuration. + +It is similar to the deprecated ``SIOCGHWTSTAMP`` ioctl request. + +Request contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Kernel response contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header + ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider + ``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type + ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter + ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +When set the ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` attribute identifies= the +source of the hw timestamping provider. It is composed by +``ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX`` attribute which describe the inde= x of +the PTP device and ``ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER`` which desc= ribe +the qualifier of the timestamp. + +When set the ``ETHTOOL_A_TSCONFIG_TX_TYPES``, ``ETHTOOL_A_TSCONFIG_RX_FILT= ERS`` +and the ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` attributes identify the Tx +type, the Rx filter and the flags configured for the current hw timestampi= ng +provider. The attributes are propagated to the driver through the following +structure: + +.. kernel-doc:: include/linux/net_tstamp.h + :identifiers: kernel_hwtstamp_config + +TSCONFIG_SET +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Set the information about the current hardware timestamping source and +configuration. + +It is similar to the deprecated ``SIOCSHWTSTAMP`` ioctl request. + +Request contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header + ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider + ``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type + ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter + ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +Kernel response contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header + ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider + ``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type + ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter + ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +For a description of each attribute, see ``TSCONFIG_GET``. + Request translation =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 @@ -2352,4 +2425,6 @@ are netlink only. n/a ``ETHTOOL_MSG_MM_SET`` n/a ``ETHTOOL_MSG_MODULE_FW_FLASH_ACT`` n/a ``ETHTOOL_MSG_PHY_GET`` + ``SIOCGHWTSTAMP`` ``ETHTOOL_MSG_TSCONFIG_GET`` + ``SIOCSHWTSTAMP`` ``ETHTOOL_MSG_TSCONFIG_SET`` =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/Documentation/networking/timestamping.rst b/Documentation/netw= orking/timestamping.rst index b37bfbfc7d79..61ef9da10e28 100644 --- a/Documentation/networking/timestamping.rst +++ b/Documentation/networking/timestamping.rst @@ -525,8 +525,8 @@ implicitly defined. ts[0] holds a software timestamp if= set, ts[1] is again deprecated and ts[2] holds a hardware timestamp if set. =20 =20 -3. Hardware Timestamping configuration: SIOCSHWTSTAMP and SIOCGHWTSTAMP -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +3. Hardware Timestamping configuration: ETHTOOL_MSG_TSCONFIG_SET/GET +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 Hardware time stamping must also be initialized for each device driver that is expected to do hardware time stamping. The parameter is defined in @@ -539,12 +539,14 @@ include/uapi/linux/net_tstamp.h as:: }; =20 Desired behavior is passed into the kernel and to a specific device by -calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose -ifr_data points to a struct hwtstamp_config. The tx_type and -rx_filter are hints to the driver what it is expected to do. If -the requested fine-grained filtering for incoming packets is not -supported, the driver may time stamp more than just the requested types -of packets. +calling the tsconfig netlink socket ``ETHTOOL_MSG_TSCONFIG_SET``. +The ``ETHTOOL_A_TSCONFIG_TX_TYPES``, ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` and +``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` netlink attributes are then used to = set +the struct hwtstamp_config accordingly. + +The ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` netlink nested attribute is u= sed +to select the source of the hardware time stamping. It is composed of an i= ndex +for the device source and a qualifier for the type of time stamping. =20 Drivers are free to use a more permissive configuration than the requested configuration. It is expected that drivers should only implement directly = the @@ -563,9 +565,16 @@ Only a processes with admin rights may change the conf= iguration. User space is responsible to ensure that multiple processes don't interfere with each other and that the settings are reset. =20 -Any process can read the actual configuration by passing this -structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has -not been implemented in all drivers. +Any process can read the actual configuration by requesting tsconfig netli= nk +socket ``ETHTOOL_MSG_TSCONFIG_GET``. + +The legacy configuration is the use of the ioctl(SIOCSHWTSTAMP) with a poi= nter +to a struct ifreq whose ifr_data points to a struct hwtstamp_config. +The tx_type and rx_filter are hints to the driver what it is expected to d= o. +If the requested fine-grained filtering for incoming packets is not +supported, the driver may time stamp more than just the requested types +of packets. ioctl(SIOCGHWTSTAMP) is used in the same way as the +ioctl(SIOCSHWTSTAMP). However, this has not been implemented in all driver= s. =20 :: =20 @@ -610,9 +619,10 @@ not been implemented in all drivers. -------------------------------------------------------- =20 A driver which supports hardware time stamping must support the -SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with -the actual values as described in the section on SIOCSHWTSTAMP. It -should also support SIOCGHWTSTAMP. +ndo_hwtstamp_set NDO or the legacy SIOCSHWTSTAMP ioctl and update the +supplied struct hwtstamp_config with the actual values as described in +the section on SIOCSHWTSTAMP. It should also support ndo_hwtstamp_get or +the legacy SIOCGHWTSTAMP. =20 Time stamps for received packets must be stored in the skb. To get a point= er to the shared time stamp structure of the skb call skb_hwtstamps(). Then diff --git a/include/uapi/linux/ethtool_netlink_generated.h b/include/uapi/= linux/ethtool_netlink_generated.h index df289dde0f61..43993a2d68e5 100644 --- a/include/uapi/linux/ethtool_netlink_generated.h +++ b/include/uapi/linux/ethtool_netlink_generated.h @@ -694,6 +694,18 @@ enum { ETHTOOL_A_PHY_MAX =3D (__ETHTOOL_A_PHY_CNT - 1) }; =20 +enum { + ETHTOOL_A_TSCONFIG_UNSPEC, + ETHTOOL_A_TSCONFIG_HEADER, + ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER, + ETHTOOL_A_TSCONFIG_TX_TYPES, + ETHTOOL_A_TSCONFIG_RX_FILTERS, + ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS, + + __ETHTOOL_A_TSCONFIG_CNT, + ETHTOOL_A_TSCONFIG_MAX =3D (__ETHTOOL_A_TSCONFIG_CNT - 1) +}; + enum { ETHTOOL_MSG_USER_NONE =3D 0, ETHTOOL_MSG_STRSET_GET =3D 1, @@ -741,6 +753,8 @@ enum { ETHTOOL_MSG_MM_SET, ETHTOOL_MSG_MODULE_FW_FLASH_ACT, ETHTOOL_MSG_PHY_GET, + ETHTOOL_MSG_TSCONFIG_GET, + ETHTOOL_MSG_TSCONFIG_SET, =20 __ETHTOOL_MSG_USER_CNT, ETHTOOL_MSG_USER_MAX =3D (__ETHTOOL_MSG_USER_CNT - 1) @@ -794,6 +808,8 @@ enum { ETHTOOL_MSG_MODULE_FW_FLASH_NTF, ETHTOOL_MSG_PHY_GET_REPLY, ETHTOOL_MSG_PHY_NTF, + ETHTOOL_MSG_TSCONFIG_GET_REPLY, + ETHTOOL_MSG_TSCONFIG_SET_REPLY, =20 __ETHTOOL_MSG_KERNEL_CNT, ETHTOOL_MSG_KERNEL_MAX =3D (__ETHTOOL_MSG_KERNEL_CNT - 1) diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index 9b540644ba31..a1490c4afe6b 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -9,4 +9,4 @@ ethtool_nl-y :=3D netlink.o bitset.o strset.o linkinfo.o li= nkmodes.o rss.o \ channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \ tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \ module.o cmis_fw_update.o cmis_cdb.o pse-pd.o plca.o mm.o \ - phy.o + phy.o tsconfig.o diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 666db40bcfda..02f941f667dd 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -797,7 +797,7 @@ int ethtool_net_get_ts_info_by_phc(struct net_device *d= ev, return -ENODEV; } =20 -int +struct phy_device * ethtool_phy_get_ts_info_by_phc(struct net_device *dev, struct kernel_ethtool_ts_info *info, struct hwtstamp_provider_desc *hwprov_desc) @@ -806,7 +806,7 @@ ethtool_phy_get_ts_info_by_phc(struct net_device *dev, =20 /* Only precise qualifier is supported in phydev */ if (hwprov_desc->qualifier !=3D HWTSTAMP_PROVIDER_QUALIFIER_PRECISE) - return -ENODEV; + return ERR_PTR(-ENODEV); =20 /* Look in the phy topology */ if (dev->link_topo) { @@ -820,12 +820,12 @@ ethtool_phy_get_ts_info_by_phc(struct net_device *dev, ethtool_init_tsinfo(info); err =3D phy_ts_info(pdn->phy, info); if (err) - return err; + return ERR_PTR(err); =20 if (info->phc_index =3D=3D hwprov_desc->index) - return 0; + return pdn->phy; } - return -ENODEV; + return ERR_PTR(-ENODEV); } =20 /* Look on the dev->phydev */ @@ -833,13 +833,13 @@ ethtool_phy_get_ts_info_by_phc(struct net_device *dev, ethtool_init_tsinfo(info); err =3D phy_ts_info(dev->phydev, info); if (err) - return err; + return ERR_PTR(err); =20 if (info->phc_index =3D=3D hwprov_desc->index) - return 0; + return dev->phydev; } =20 - return -ENODEV; + return ERR_PTR(-ENODEV); } =20 int ethtool_get_ts_info_by_phc(struct net_device *dev, @@ -849,8 +849,15 @@ int ethtool_get_ts_info_by_phc(struct net_device *dev, int err; =20 err =3D ethtool_net_get_ts_info_by_phc(dev, info, hwprov_desc); - if (err =3D=3D -ENODEV) - err =3D ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc); + if (err =3D=3D -ENODEV) { + struct phy_device *phy; + + phy =3D ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc); + if (IS_ERR(phy)) + err =3D PTR_ERR(phy); + else + err =3D 0; + } =20 info->so_timestamping |=3D SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; diff --git a/net/ethtool/common.h b/net/ethtool/common.h index f5119204c8ff..850eadde4bfc 100644 --- a/net/ethtool/common.h +++ b/net/ethtool/common.h @@ -56,7 +56,7 @@ int ethtool_get_ts_info_by_phc(struct net_device *dev, int ethtool_net_get_ts_info_by_phc(struct net_device *dev, struct kernel_ethtool_ts_info *info, struct hwtstamp_provider_desc *hwprov_desc); -int +struct phy_device * ethtool_phy_get_ts_info_by_phc(struct net_device *dev, struct kernel_ethtool_ts_info *info, struct hwtstamp_provider_desc *hwprov_desc); diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 6ae1d91f36e7..849c98e637c6 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -394,6 +394,8 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] =3D { [ETHTOOL_MSG_PLCA_GET_STATUS] =3D ðnl_plca_status_request_ops, [ETHTOOL_MSG_MM_GET] =3D ðnl_mm_request_ops, [ETHTOOL_MSG_MM_SET] =3D ðnl_mm_request_ops, + [ETHTOOL_MSG_TSCONFIG_GET] =3D ðnl_tsconfig_request_ops, + [ETHTOOL_MSG_TSCONFIG_SET] =3D ðnl_tsconfig_request_ops, }; =20 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *= cb) @@ -1243,6 +1245,22 @@ static const struct genl_ops ethtool_genl_ops[] =3D { .policy =3D ethnl_phy_get_policy, .maxattr =3D ARRAY_SIZE(ethnl_phy_get_policy) - 1, }, + { + .cmd =3D ETHTOOL_MSG_TSCONFIG_GET, + .doit =3D ethnl_default_doit, + .start =3D ethnl_default_start, + .dumpit =3D ethnl_default_dumpit, + .done =3D ethnl_default_done, + .policy =3D ethnl_tsconfig_get_policy, + .maxattr =3D ARRAY_SIZE(ethnl_tsconfig_get_policy) - 1, + }, + { + .cmd =3D ETHTOOL_MSG_TSCONFIG_SET, + .flags =3D GENL_UNS_ADMIN_PERM, + .doit =3D ethnl_default_set_doit, + .policy =3D ethnl_tsconfig_set_policy, + .maxattr =3D ARRAY_SIZE(ethnl_tsconfig_set_policy) - 1, + }, }; =20 static const struct genl_multicast_group ethtool_nl_mcgrps[] =3D { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 960cda13e4fc..0a09298fff92 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -435,6 +435,7 @@ extern const struct ethnl_request_ops ethnl_plca_cfg_re= quest_ops; extern const struct ethnl_request_ops ethnl_plca_status_request_ops; extern const struct ethnl_request_ops ethnl_mm_request_ops; extern const struct ethnl_request_ops ethnl_phy_request_ops; +extern const struct ethnl_request_ops ethnl_tsconfig_request_ops; =20 extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS = + 1]; extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_= FLAGS + 1]; @@ -485,6 +486,8 @@ extern const struct nla_policy ethnl_mm_get_policy[ETHT= OOL_A_MM_HEADER + 1]; extern const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1]; extern const struct nla_policy ethnl_module_fw_flash_act_policy[ETHTOOL_A_= MODULE_FW_FLASH_PASSWORD + 1]; extern const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER += 1]; +extern const struct nla_policy ethnl_tsconfig_get_policy[ETHTOOL_A_TSCONFI= G_HEADER + 1]; +extern const struct nla_policy ethnl_tsconfig_set_policy[ETHTOOL_A_TSCONFI= G_MAX + 1]; =20 int ethnl_set_features(struct sk_buff *skb, struct genl_info *info); int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info); diff --git a/net/ethtool/tsconfig.c b/net/ethtool/tsconfig.c new file mode 100644 index 000000000000..9188e088fb2f --- /dev/null +++ b/net/ethtool/tsconfig.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include "netlink.h" +#include "common.h" +#include "bitset.h" +#include "../core/dev.h" +#include "ts.h" + +struct tsconfig_req_info { + struct ethnl_req_info base; +}; + +struct tsconfig_reply_data { + struct ethnl_reply_data base; + struct hwtstamp_provider_desc hwprov_desc; + struct { + u32 tx_type; + u32 rx_filter; + u32 flags; + } hwtst_config; +}; + +#define TSCONFIG_REPDATA(__reply_base) \ + container_of(__reply_base, struct tsconfig_reply_data, base) + +const struct nla_policy ethnl_tsconfig_get_policy[ETHTOOL_A_TSCONFIG_HEADE= R + 1] =3D { + [ETHTOOL_A_TSCONFIG_HEADER] =3D + NLA_POLICY_NESTED(ethnl_header_policy), +}; + +static int tsconfig_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + const struct genl_info *info) +{ + struct tsconfig_reply_data *data =3D TSCONFIG_REPDATA(reply_base); + struct hwtstamp_provider *hwprov =3D NULL; + struct net_device *dev =3D reply_base->dev; + struct kernel_hwtstamp_config cfg =3D {}; + int ret; + + if (!dev->netdev_ops->ndo_hwtstamp_get) + return -EOPNOTSUPP; + + ret =3D ethnl_ops_begin(dev); + if (ret < 0) + return ret; + + ret =3D dev_get_hwtstamp_phylib(dev, &cfg); + if (ret) + goto out; + + data->hwtst_config.tx_type =3D BIT(cfg.tx_type); + data->hwtst_config.rx_filter =3D BIT(cfg.rx_filter); + data->hwtst_config.flags =3D BIT(cfg.flags); + + data->hwprov_desc.index =3D -1; + hwprov =3D rtnl_dereference(dev->hwprov); + if (hwprov) { + data->hwprov_desc.index =3D hwprov->desc.index; + data->hwprov_desc.qualifier =3D hwprov->desc.qualifier; + } else { + struct kernel_ethtool_ts_info ts_info =3D {}; + + ts_info.phc_index =3D -1; + ret =3D __ethtool_get_ts_info(dev, &ts_info); + if (ret) + goto out; + + if (ts_info.phc_index =3D=3D -1) + return -ENODEV; + + data->hwprov_desc.index =3D ts_info.phc_index; + data->hwprov_desc.qualifier =3D ts_info.phc_qualifier; + } + +out: + ethnl_ops_complete(dev); + return ret; +} + +static int tsconfig_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct tsconfig_reply_data *data =3D TSCONFIG_REPDATA(reply_base); + bool compact =3D req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; + int len =3D 0; + int ret; + + BUILD_BUG_ON(__HWTSTAMP_TX_CNT > 32); + BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT > 32); + + if (data->hwtst_config.flags) + /* _TSCONFIG_HWTSTAMP_FLAGS */ + len +=3D nla_total_size(sizeof(u32)); + + if (data->hwtst_config.tx_type) { + ret =3D ethnl_bitset32_size(&data->hwtst_config.tx_type, + NULL, __HWTSTAMP_TX_CNT, + ts_tx_type_names, compact); + if (ret < 0) + return ret; + len +=3D ret; /* _TSCONFIG_TX_TYPES */ + } + if (data->hwtst_config.rx_filter) { + ret =3D ethnl_bitset32_size(&data->hwtst_config.rx_filter, + NULL, __HWTSTAMP_FILTER_CNT, + ts_rx_filter_names, compact); + if (ret < 0) + return ret; + len +=3D ret; /* _TSCONFIG_RX_FILTERS */ + } + + if (data->hwprov_desc.index >=3D 0) + /* _TSCONFIG_HWTSTAMP_PROVIDER */ + len +=3D nla_total_size(0) + + 2 * nla_total_size(sizeof(u32)); + + return len; +} + +static int tsconfig_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct tsconfig_reply_data *data =3D TSCONFIG_REPDATA(reply_base); + bool compact =3D req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; + int ret; + + if (data->hwtst_config.flags) { + ret =3D nla_put_u32(skb, ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS, + data->hwtst_config.flags); + if (ret < 0) + return ret; + } + + if (data->hwtst_config.tx_type) { + ret =3D ethnl_put_bitset32(skb, ETHTOOL_A_TSCONFIG_TX_TYPES, + &data->hwtst_config.tx_type, NULL, + __HWTSTAMP_TX_CNT, + ts_tx_type_names, compact); + if (ret < 0) + return ret; + } + + if (data->hwtst_config.rx_filter) { + ret =3D ethnl_put_bitset32(skb, ETHTOOL_A_TSCONFIG_RX_FILTERS, + &data->hwtst_config.rx_filter, + NULL, __HWTSTAMP_FILTER_CNT, + ts_rx_filter_names, compact); + if (ret < 0) + return ret; + } + + if (data->hwprov_desc.index >=3D 0) { + struct nlattr *nest; + + nest =3D nla_nest_start(skb, ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER); + if (!nest) + return -EMSGSIZE; + + if (nla_put_u32(skb, ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX, + data->hwprov_desc.index) || + nla_put_u32(skb, + ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER, + data->hwprov_desc.qualifier)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + + nla_nest_end(skb, nest); + } + return 0; +} + +/* TSCONFIG_SET */ +const struct nla_policy ethnl_tsconfig_set_policy[ETHTOOL_A_TSCONFIG_MAX += 1] =3D { + [ETHTOOL_A_TSCONFIG_HEADER] =3D NLA_POLICY_NESTED(ethnl_header_policy), + [ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER] =3D + NLA_POLICY_NESTED(ethnl_ts_hwtst_prov_policy), + [ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS] =3D { .type =3D NLA_U32 }, + [ETHTOOL_A_TSCONFIG_RX_FILTERS] =3D { .type =3D NLA_NESTED }, + [ETHTOOL_A_TSCONFIG_TX_TYPES] =3D { .type =3D NLA_NESTED }, +}; + +static int tsconfig_send_reply(struct net_device *dev, struct genl_info *i= nfo) +{ + struct tsconfig_reply_data *reply_data; + struct tsconfig_req_info *req_info; + struct sk_buff *rskb; + void *reply_payload; + int reply_len =3D 0; + int ret; + + req_info =3D kzalloc(sizeof(*req_info), GFP_KERNEL); + if (!req_info) + return -ENOMEM; + reply_data =3D kmalloc(sizeof(*reply_data), GFP_KERNEL); + if (!reply_data) { + kfree(req_info); + return -ENOMEM; + } + + ASSERT_RTNL(); + reply_data->base.dev =3D dev; + ret =3D tsconfig_prepare_data(&req_info->base, &reply_data->base, info); + if (ret < 0) + goto err_cleanup; + + ret =3D tsconfig_reply_size(&req_info->base, &reply_data->base); + if (ret < 0) + goto err_cleanup; + + reply_len =3D ret + ethnl_reply_header_size(); + rskb =3D ethnl_reply_init(reply_len, dev, ETHTOOL_MSG_TSCONFIG_SET_REPLY, + ETHTOOL_A_TSCONFIG_HEADER, info, &reply_payload); + if (!rskb) + goto err_cleanup; + + ret =3D tsconfig_fill_reply(rskb, &req_info->base, &reply_data->base); + if (ret < 0) + goto err_cleanup; + + genlmsg_end(rskb, reply_payload); + ret =3D genlmsg_reply(rskb, info); + +err_cleanup: + kfree(reply_data); + kfree(req_info); + return ret; +} + +static int ethnl_set_tsconfig_validate(struct ethnl_req_info *req_base, + struct genl_info *info) +{ + const struct net_device_ops *ops =3D req_base->dev->netdev_ops; + + if (!ops->ndo_hwtstamp_set || !ops->ndo_hwtstamp_get) + return -EOPNOTSUPP; + + return 1; +} + +static struct hwtstamp_provider * +tsconfig_set_hwprov_from_desc(struct net_device *dev, + struct genl_info *info, + struct hwtstamp_provider_desc *hwprov_desc) +{ + struct kernel_ethtool_ts_info ts_info; + struct hwtstamp_provider *hwprov; + struct nlattr **tb =3D info->attrs; + struct phy_device *phy =3D NULL; + enum hwtstamp_source source; + int ret; + + ret =3D ethtool_net_get_ts_info_by_phc(dev, &ts_info, hwprov_desc); + if (!ret) { + /* Found */ + source =3D HWTSTAMP_SOURCE_NETDEV; + } else { + phy =3D ethtool_phy_get_ts_info_by_phc(dev, &ts_info, hwprov_desc); + if (IS_ERR(phy)) { + if (PTR_ERR(phy) =3D=3D -ENODEV) + NL_SET_ERR_MSG_ATTR(info->extack, + tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER], + "phc not in this net device topology"); + return ERR_CAST(phy); + } + + source =3D HWTSTAMP_SOURCE_PHYLIB; + } + + hwprov =3D kzalloc(sizeof(*hwprov), GFP_KERNEL); + if (!hwprov) + return ERR_PTR(-ENOMEM); + + hwprov->desc.index =3D hwprov_desc->index; + hwprov->desc.qualifier =3D hwprov_desc->qualifier; + hwprov->source =3D source; + hwprov->phydev =3D phy; + + return hwprov; +} + +static int ethnl_set_tsconfig(struct ethnl_req_info *req_base, + struct genl_info *info) +{ + struct kernel_hwtstamp_config hwtst_config =3D {0}; + bool hwprov_mod =3D false, config_mod =3D false; + struct hwtstamp_provider *hwprov =3D NULL; + struct net_device *dev =3D req_base->dev; + struct nlattr **tb =3D info->attrs; + int ret; + + BUILD_BUG_ON(__HWTSTAMP_TX_CNT >=3D 32); + BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT >=3D 32); + + if (!netif_device_present(dev)) + return -ENODEV; + + if (tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER]) { + struct hwtstamp_provider_desc __hwprov_desc =3D {.index =3D -1}; + struct hwtstamp_provider *__hwprov; + + __hwprov =3D rtnl_dereference(dev->hwprov); + if (__hwprov) { + __hwprov_desc.index =3D __hwprov->desc.index; + __hwprov_desc.qualifier =3D __hwprov->desc.qualifier; + } + + ret =3D ts_parse_hwtst_provider(tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER], + &__hwprov_desc, info->extack, + &hwprov_mod); + if (ret < 0) + return ret; + + if (hwprov_mod) { + hwprov =3D tsconfig_set_hwprov_from_desc(dev, info, + &__hwprov_desc); + if (IS_ERR(hwprov)) + return PTR_ERR(hwprov); + } + } + + /* Get current hwtstamp config if we are not changing the + * hwtstamp source. It will be zeroed in the other case. + */ + if (!hwprov_mod) { + ret =3D dev_get_hwtstamp_phylib(dev, &hwtst_config); + if (ret < 0 && ret !=3D -EOPNOTSUPP) + goto err_free_hwprov; + } + + /* Get the hwtstamp config from netlink */ + if (tb[ETHTOOL_A_TSCONFIG_TX_TYPES]) { + u32 req_tx_type; + + req_tx_type =3D BIT(hwtst_config.tx_type); + ret =3D ethnl_update_bitset32(&req_tx_type, + __HWTSTAMP_TX_CNT, + tb[ETHTOOL_A_TSCONFIG_TX_TYPES], + ts_tx_type_names, info->extack, + &config_mod); + if (ret < 0) + goto err_free_hwprov; + + /* Select only one tx type at a time */ + if (ffs(req_tx_type) !=3D fls(req_tx_type)) { + ret =3D -EINVAL; + goto err_free_hwprov; + } + + hwtst_config.tx_type =3D ffs(req_tx_type) - 1; + } + + if (tb[ETHTOOL_A_TSCONFIG_RX_FILTERS]) { + u32 req_rx_filter; + + req_rx_filter =3D BIT(hwtst_config.rx_filter); + ret =3D ethnl_update_bitset32(&req_rx_filter, + __HWTSTAMP_FILTER_CNT, + tb[ETHTOOL_A_TSCONFIG_RX_FILTERS], + ts_rx_filter_names, info->extack, + &config_mod); + if (ret < 0) + goto err_free_hwprov; + + /* Select only one rx filter at a time */ + if (ffs(req_rx_filter) !=3D fls(req_rx_filter)) { + ret =3D -EINVAL; + goto err_free_hwprov; + } + + hwtst_config.rx_filter =3D ffs(req_rx_filter) - 1; + } + + if (tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS]) { + ethnl_update_u32(&hwtst_config.flags, + tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS], + &config_mod); + } + + ret =3D net_hwtstamp_validate(&hwtst_config); + if (ret) + goto err_free_hwprov; + + if (hwprov_mod) { + struct kernel_hwtstamp_config zero_config =3D {0}; + struct hwtstamp_provider *__hwprov; + + /* Disable current time stamping if we try to enable + * another one + */ + ret =3D dev_set_hwtstamp_phylib(dev, &zero_config, info->extack); + if (ret < 0) + goto err_free_hwprov; + + /* Change the selected hwtstamp source */ + __hwprov =3D rcu_replace_pointer_rtnl(dev->hwprov, hwprov); + if (__hwprov) + kfree_rcu(__hwprov, rcu_head); + } + + if (config_mod) { + ret =3D dev_set_hwtstamp_phylib(dev, &hwtst_config, + info->extack); + if (ret < 0) + return ret; + } + + if (hwprov_mod || config_mod) { + ret =3D tsconfig_send_reply(dev, info); + if (ret && ret !=3D -EOPNOTSUPP) { + NL_SET_ERR_MSG(info->extack, + "error while reading the new configuration set"); + return ret; + } + } + + /* tsconfig has no notification */ + return 0; + +err_free_hwprov: + kfree(hwprov); + + return ret; +} + +const struct ethnl_request_ops ethnl_tsconfig_request_ops =3D { + .request_cmd =3D ETHTOOL_MSG_TSCONFIG_GET, + .reply_cmd =3D ETHTOOL_MSG_TSCONFIG_GET_REPLY, + .hdr_attr =3D ETHTOOL_A_TSCONFIG_HEADER, + .req_info_size =3D sizeof(struct tsconfig_req_info), + .reply_data_size =3D sizeof(struct tsconfig_reply_data), + + .prepare_data =3D tsconfig_prepare_data, + .reply_size =3D tsconfig_reply_size, + .fill_reply =3D tsconfig_fill_reply, + + .set_validate =3D ethnl_set_tsconfig_validate, + .set =3D ethnl_set_tsconfig, +}; --=20 2.34.1