diff --git a/arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c b/arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c index 7d87b5328a779..c725636dcf765 100644 --- a/arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c +++ b/arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c @@ -4604,6 +4604,9 @@ int stm32_ethinitialize(int intf) #ifdef CONFIG_STM32_ETH_TIMESTAMP_RX priv->dev.d_features |= NETDEV_RX_STAMP; #endif +#ifdef CONFIG_STM32_ETH_TIMESTAMP_TX + priv->dev.d_features |= NETDEV_TX_STAMP; +#endif /* Register the device with the OS so that socket IOCTLs can be performed */ diff --git a/arch/arm/src/stm32h7/stm32_ethernet.c b/arch/arm/src/stm32h7/stm32_ethernet.c index db001b991ca2c..76a3b97c74dfd 100644 --- a/arch/arm/src/stm32h7/stm32_ethernet.c +++ b/arch/arm/src/stm32h7/stm32_ethernet.c @@ -5161,6 +5161,10 @@ static inline int stm32_ethinitialize(int intf) priv->dev.d_features |= NETDEV_RX_STAMP; #endif +#ifdef CONFIG_STM32_ETH_TIMESTAMP_TX + priv->dev.d_features |= NETDEV_TX_STAMP; +#endif + /* Register the device with the OS so that socket IOCTLs can be performed */ netdev_register(&priv->dev, NET_LL_ETHERNET); diff --git a/include/nuttx/ethtool.h b/include/nuttx/ethtool.h index 26412a6a1f4a5..87cd3f0e1d5d5 100644 --- a/include/nuttx/ethtool.h +++ b/include/nuttx/ethtool.h @@ -23,6 +23,12 @@ #ifndef __INCLUDE_NUTTX_ETHTOOL_H #define __INCLUDE_NUTTX_ETHTOOL_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -221,4 +227,29 @@ struct ethtool_cmd uint32_t reserved[2]; }; +/* struct ethtool_ts_info - holds a device's timestamping and PHC + * association (ETHTOOL_GET_TS_INFO), same layout as Linux. + * @cmd: command number = %ETHTOOL_GET_TS_INFO + * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING + * flags (SOF_TIMESTAMPING_*) + * @phc_index: device index of the associated PHC, or -1 if there is none + * @tx_types: bit mask of the supported hwtstamp_tx_types values; zero, + * NuttX has no SIOCSHWTSTAMP to select them + * @tx_reserved: reserved for future use, zero + * @rx_filters: bit mask of the supported hwtstamp_rx_filters values; zero, + * NuttX has no SIOCSHWTSTAMP to select them + * @rx_reserved: reserved for future use, zero + */ + +struct ethtool_ts_info +{ + uint32_t cmd; + uint32_t so_timestamping; + int32_t phc_index; + uint32_t tx_types; + uint32_t tx_reserved[3]; + uint32_t rx_filters; + uint32_t rx_reserved[3]; +}; + #endif diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index c5395ba67cdc9..a5a78c078c7e4 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -85,6 +85,7 @@ #define NETDEV_TX_CSUM (1 << 1) /* Netdev support hardware tx checksum */ #define NETDEV_RX_CSUM (1 << 2) /* Netdev support hardware rx checksum */ #define NETDEV_RX_STAMP (1 << 3) /* Netdev support hardware timestamp */ +#define NETDEV_TX_STAMP (1 << 4) /* Netdev provides hardware TX timestamps */ /* Determine the largest possible address */ diff --git a/include/sys/socket.h b/include/sys/socket.h index 50424bff924e8..6471fdc2f0ab0 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -230,15 +230,24 @@ #define __SO_PROTOCOL 16 +/* SO_TIMESTAMPING flags, with the same values as Linux so that they can + * also describe the capabilities of an interface (ETHTOOL_GET_TS_INFO). + * setsockopt(SO_TIMESTAMPING) currently treats any non-zero value as + * "enabled" and does not honour the individual flags. + */ + /* Timestamp generation */ -#define SOF_TIMESTAMPING_TX_HARDWARE (1 << SO_TIMESTAMPING) -#define SOF_TIMESTAMPING_TX_SOFTWARE SOF_TIMESTAMPING_TX_HARDWARE +#define SOF_TIMESTAMPING_TX_HARDWARE (1 << 0) +#define SOF_TIMESTAMPING_TX_SOFTWARE (1 << 1) +#define SOF_TIMESTAMPING_RX_HARDWARE (1 << 2) +#define SOF_TIMESTAMPING_RX_SOFTWARE (1 << 3) /* Timestamp reporting */ -#define SOF_TIMESTAMPING_SOFTWARE SOF_TIMESTAMPING_TX_SOFTWARE -#define SOF_TIMESTAMPING_RAW_HARDWARE SOF_TIMESTAMPING_TX_HARDWARE +#define SOF_TIMESTAMPING_SOFTWARE (1 << 4) +#define SOF_TIMESTAMPING_SYS_HARDWARE (1 << 5) +#define SOF_TIMESTAMPING_RAW_HARDWARE (1 << 6) /* The options are unsupported but included for compatibility * and portability diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 4f6610f43963a..1b846e30e6148 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -767,6 +768,7 @@ static ssize_t net_ioctl_ifreq_arglen(uint8_t domain, int cmd) case SIOCGIFCOUNT: case SIOCSIFFLAGS: case SIOCGIFFLAGS: + case SIOCETHTOOL: case SIOCMIINOTIFY: case SIOCGMIIPHY: case SIOCGMIIREG: @@ -809,6 +811,85 @@ static ssize_t net_ioctl_ifreq_arglen(uint8_t domain, int cmd) return -ENOTTY; } +/**************************************************************************** + * Name: netdev_ethtool_ioctl + * + * Description: + * Handle the SIOCETHTOOL command. req->ifr_data points to an ethtool + * command structure whose first field is the ETHTOOL_* command. + * ETHTOOL_GET_TS_INFO is answered from the device features; any other + * command is passed to the driver. + * + * Input Parameters: + * dev The network device + * req The argument of the ioctl cmd + * + * Returned Value: + * >=0 on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +static int netdev_ethtool_ioctl(FAR struct net_driver_s *dev, + FAR struct ifreq *req) +{ + FAR uint32_t *ethcmd = req->ifr_data; + + if (ethcmd == NULL) + { + return -EINVAL; + } + + switch (*ethcmd) + { + case ETHTOOL_GET_TS_INFO: /* Get time stamping and PHC info */ + { + FAR struct ethtool_ts_info *info = req->ifr_data; + + memset(info, 0, sizeof(*info)); + info->cmd = ETHTOOL_GET_TS_INFO; + info->phc_index = -1; + +#ifdef CONFIG_NET_TIMESTAMP + /* Received packets carry the hardware timestamp when the driver + * provides one, and are stamped by the stack with CLOCK_REALTIME + * otherwise. + */ + + if ((dev->d_features & NETDEV_RX_STAMP) != 0) + { + info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + } + else + { + info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + } + + if ((dev->d_features & NETDEV_TX_STAMP) != 0) + { + info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + } +#endif + + return OK; + } + + default: +#ifdef CONFIG_NETDEV_IOCTL + if (dev->d_ioctl != NULL) + { + return dev->d_ioctl(dev, SIOCETHTOOL, + (unsigned long)(uintptr_t)req->ifr_data); + } +#endif + + return -ENOTTY; + } +} + /**************************************************************************** * Name: netdev_ifr_ioctl * @@ -1088,6 +1169,10 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, req->ifr_flags = dev->d_flags; break; + case SIOCETHTOOL: /* Ethtool interface */ + ret = netdev_ethtool_ioctl(dev, req); + break; + /* MAC address operations only make sense if Ethernet or 6LoWPAN are * supported. */