struct ethtool_set_features_block features[0];
 };
 
+/**
+ * struct ethtool_ts_info - holds a device's timestamping and PHC association
+ * @cmd: command number = %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
+ * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values
+ * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values
+ *
+ * The bits in the 'tx_types' and 'rx_filters' fields correspond to
+ * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values,
+ * respectively.  For example, if the device supports HWTSTAMP_TX_ON,
+ * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set.
+ */
+struct ethtool_ts_info {
+       __u32   cmd;
+       __u32   so_timestamping;
+       __s32   phc_index;
+       __u32   tx_types;
+       __u32   tx_reserved[3];
+       __u32   rx_filters;
+       __u32   rx_reserved[3];
+};
+
 /*
  * %ETHTOOL_SFEATURES changes features present in features[].valid to the
  * values of corresponding bits in features[].requested. Bits in .requested
  *                and flag of the device.
  * @get_dump_data: Get dump data.
  * @set_dump: Set dump specific flags to the device.
+ * @get_ts_info: Get the time stamping and PTP hardware clock capabilities.
+ *     Drivers supporting transmit time stamps in software should set this to
+ *     ethtool_op_get_ts_info().
  *
  * All operations are optional (i.e. the function pointer may be set
  * to %NULL) and callers must take this into account.  Callers must
        int     (*get_dump_data)(struct net_device *,
                                 struct ethtool_dump *, void *);
        int     (*set_dump)(struct net_device *, struct ethtool_dump *);
+       int     (*get_ts_info)(struct net_device *, struct ethtool_ts_info *);
 
 };
 #endif /* __KERNEL__ */
 #define ETHTOOL_SET_DUMP       0x0000003e /* Set dump settings */
 #define ETHTOOL_GET_DUMP_FLAG  0x0000003f /* Get dump settings */
 #define ETHTOOL_GET_DUMP_DATA  0x00000040 /* Get dump data */
+#define ETHTOOL_GET_TS_INFO    0x00000041 /* Get time stamping and PHC info */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET         ETHTOOL_GSET
 
 #include <linux/errno.h>
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
+#include <linux/phy.h>
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
        return ret;
 }
 
+static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr)
+{
+       int err = 0;
+       struct ethtool_ts_info info;
+       const struct ethtool_ops *ops = dev->ethtool_ops;
+       struct phy_device *phydev = dev->phydev;
+
+       memset(&info, 0, sizeof(info));
+       info.cmd = ETHTOOL_GET_TS_INFO;
+
+       if (phydev && phydev->drv && phydev->drv->ts_info) {
+
+               err = phydev->drv->ts_info(phydev, &info);
+
+       } else if (dev->ethtool_ops && dev->ethtool_ops->get_ts_info) {
+
+               err = ops->get_ts_info(dev, &info);
+
+       } else {
+               info.so_timestamping =
+                       SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE;
+               info.phc_index = -1;
+       }
+
+       if (err)
+               return err;
+
+       if (copy_to_user(useraddr, &info, sizeof(info)))
+               err = -EFAULT;
+
+       return err;
+}
+
 /* The main entry point in this file.  Called from net/core/dev.c */
 
 int dev_ethtool(struct net *net, struct ifreq *ifr)
                return -EFAULT;
 
        if (!dev->ethtool_ops) {
-               /* ETHTOOL_GDRVINFO does not require any driver support.
-                * It is also unprivileged and does not change anything,
-                * so we can take a shortcut to it. */
+               /* A few commands do not require any driver support,
+                * are unprivileged, and do not change anything, so we
+                * can take a shortcut to them. */
                if (ethcmd == ETHTOOL_GDRVINFO)
                        return ethtool_get_drvinfo(dev, useraddr);
+               else if (ethcmd == ETHTOOL_GET_TS_INFO)
+                       return ethtool_get_ts_info(dev, useraddr);
                else
                        return -EOPNOTSUPP;
        }
        case ETHTOOL_GRXCLSRULE:
        case ETHTOOL_GRXCLSRLALL:
        case ETHTOOL_GFEATURES:
+       case ETHTOOL_GET_TS_INFO:
                break;
        default:
                if (!capable(CAP_NET_ADMIN))
        case ETHTOOL_GET_DUMP_DATA:
                rc = ethtool_get_dump_data(dev, useraddr);
                break;
+       case ETHTOOL_GET_TS_INFO:
+               rc = ethtool_get_ts_info(dev, useraddr);
+               break;
        default:
                rc = -EOPNOTSUPP;
        }