[v3,2/5] net: Expose available time stamping layers to user space.
Commit Message
From: Kory Maincent <kory.maincent@bootlin.com>
Time stamping on network packets may happen either in the MAC or in
the PHY, but not both. In preparation for making the choice
selectable, expose both the current and available layers via ethtool.
In accordance with the kernel implementation as it stands, the current
layer will always read as "phy" when a PHY time stamping device is
present. Future patches will allow changing the current layer
administratively.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
---
Notes:
Changes in v2:
- Move the introduction of selected_timestamping_layer variable in next
patch.
Changes in v3:
- Move on to ethtool instead of syfs
Documentation/networking/ethtool-netlink.rst | 2 +
include/uapi/linux/ethtool.h | 2 +
include/uapi/linux/net_tstamp.h | 6 +++
net/ethtool/ioctl.c | 50 ++++++++++++++++++++
4 files changed, 60 insertions(+)
Comments
Hi Köry,
On Wed, Mar 08, 2023 at 02:59:26PM +0100, Köry Maincent wrote:
> From: Kory Maincent <kory.maincent@bootlin.com>
>
> Time stamping on network packets may happen either in the MAC or in
> the PHY, but not both. In preparation for making the choice
> selectable, expose both the current and available layers via ethtool.
>
> In accordance with the kernel implementation as it stands, the current
> layer will always read as "phy" when a PHY time stamping device is
> present. Future patches will allow changing the current layer
> administratively.
>
> Signed-off-by: Richard Cochran <richardcochran@gmail.com>
> Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
> ---
I'm pretty sure that all new ethtool commands must be implemented
through the genetlink socket interface. The ioctl interface stopped
being extended and is in maintenance mode only.
@@ -1787,4 +1787,6 @@ are netlink only.
n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET``
n/a ``ETHTOOL_MSG_MODULE_GET``
n/a ``ETHTOOL_MSG_MODULE_SET``
+ ``ETHTOOL_LIST_PTP`` n/a
+ ``ETHTOOL_GET_PTP`` n/a
=================================== =====================================
@@ -1629,6 +1629,8 @@ enum ethtool_fec_config_bits {
#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */
#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */
#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */
+#define ETHTOOL_LIST_PTP 0x00000052 /* List PTP providers */
+#define ETHTOOL_GET_PTP 0x00000053 /* Get current PTP provider */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
@@ -13,6 +13,12 @@
#include <linux/types.h>
#include <linux/socket.h> /* for SO_TIMESTAMPING */
+/* Hardware layer of the SO_TIMESTAMPING provider */
+enum timestamping_layer {
+ MAC_TIMESTAMPING = (1<<0),
+ PHY_TIMESTAMPING = (1<<1),
+};
+
/* SO_TIMESTAMPING flags */
enum {
SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
@@ -2319,6 +2319,48 @@ static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr)
return 0;
}
+static int ethtool_list_ptp(struct net_device *dev, void __user *useraddr)
+{
+ struct ethtool_value edata = {
+ .cmd = ETHTOOL_LIST_PTP,
+ .data = 0,
+ };
+ struct phy_device *phydev = dev->phydev;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+
+ if (phy_has_tsinfo(phydev))
+ edata.data = PHY_TIMESTAMPING;
+ if (ops->get_ts_info)
+ edata.data |= MAC_TIMESTAMPING;
+
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int ethtool_get_ptp(struct net_device *dev, void __user *useraddr)
+{
+ struct ethtool_value edata = {
+ .cmd = ETHTOOL_GET_PTP,
+ .data = 0,
+ };
+ struct phy_device *phydev = dev->phydev;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+
+ if (phy_has_tsinfo(phydev))
+ edata.data = PHY_TIMESTAMPING;
+ else if (ops->get_ts_info)
+ edata.data = MAC_TIMESTAMPING;
+ else
+ return -EOPNOTSUPP;
+
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+
+ return 0;
+}
+
int ethtool_get_module_info_call(struct net_device *dev,
struct ethtool_modinfo *modinfo)
{
@@ -2770,6 +2812,8 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr,
case ETHTOOL_PHY_GTUNABLE:
case ETHTOOL_GLINKSETTINGS:
case ETHTOOL_GFECPARAM:
+ case ETHTOOL_LIST_PTP:
+ case ETHTOOL_GET_PTP:
break;
default:
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
@@ -2997,6 +3041,12 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr,
case ETHTOOL_SFECPARAM:
rc = ethtool_set_fecparam(dev, useraddr);
break;
+ case ETHTOOL_LIST_PTP:
+ rc = ethtool_list_ptp(dev, useraddr);
+ break;
+ case ETHTOOL_GET_PTP:
+ rc = ethtool_get_ptp(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}