aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ethtool.h28
-rw-r--r--include/linux/phy.h3
-rw-r--r--net/core/ethtool.c48
3 files changed, 76 insertions, 3 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index e1d9e0ede309..1769714447b3 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -726,6 +726,29 @@ struct ethtool_sfeatures {
726 struct ethtool_set_features_block features[0]; 726 struct ethtool_set_features_block features[0];
727}; 727};
728 728
729/**
730 * struct ethtool_ts_info - holds a device's timestamping and PHC association
731 * @cmd: command number = %ETHTOOL_GET_TS_INFO
732 * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags
733 * @phc_index: device index of the associated PHC, or -1 if there is none
734 * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values
735 * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values
736 *
737 * The bits in the 'tx_types' and 'rx_filters' fields correspond to
738 * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values,
739 * respectively. For example, if the device supports HWTSTAMP_TX_ON,
740 * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set.
741 */
742struct ethtool_ts_info {
743 __u32 cmd;
744 __u32 so_timestamping;
745 __s32 phc_index;
746 __u32 tx_types;
747 __u32 tx_reserved[3];
748 __u32 rx_filters;
749 __u32 rx_reserved[3];
750};
751
729/* 752/*
730 * %ETHTOOL_SFEATURES changes features present in features[].valid to the 753 * %ETHTOOL_SFEATURES changes features present in features[].valid to the
731 * values of corresponding bits in features[].requested. Bits in .requested 754 * values of corresponding bits in features[].requested. Bits in .requested
@@ -893,6 +916,9 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
893 * and flag of the device. 916 * and flag of the device.
894 * @get_dump_data: Get dump data. 917 * @get_dump_data: Get dump data.
895 * @set_dump: Set dump specific flags to the device. 918 * @set_dump: Set dump specific flags to the device.
919 * @get_ts_info: Get the time stamping and PTP hardware clock capabilities.
920 * Drivers supporting transmit time stamps in software should set this to
921 * ethtool_op_get_ts_info().
896 * 922 *
897 * All operations are optional (i.e. the function pointer may be set 923 * All operations are optional (i.e. the function pointer may be set
898 * to %NULL) and callers must take this into account. Callers must 924 * to %NULL) and callers must take this into account. Callers must
@@ -955,6 +981,7 @@ struct ethtool_ops {
955 int (*get_dump_data)(struct net_device *, 981 int (*get_dump_data)(struct net_device *,
956 struct ethtool_dump *, void *); 982 struct ethtool_dump *, void *);
957 int (*set_dump)(struct net_device *, struct ethtool_dump *); 983 int (*set_dump)(struct net_device *, struct ethtool_dump *);
984 int (*get_ts_info)(struct net_device *, struct ethtool_ts_info *);
958 985
959}; 986};
960#endif /* __KERNEL__ */ 987#endif /* __KERNEL__ */
@@ -1029,6 +1056,7 @@ struct ethtool_ops {
1029#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ 1056#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */
1030#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ 1057#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */
1031#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ 1058#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */
1059#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */
1032 1060
1033/* compatibility with older code */ 1061/* compatibility with older code */
1034#define SPARC_ETH_GSET ETHTOOL_GSET 1062#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 6fe0a37d4abf..f092032f1c98 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -412,6 +412,9 @@ struct phy_driver {
412 /* Clears up any memory if needed */ 412 /* Clears up any memory if needed */
413 void (*remove)(struct phy_device *phydev); 413 void (*remove)(struct phy_device *phydev);
414 414
415 /* Handles ethtool queries for hardware time stamping. */
416 int (*ts_info)(struct phy_device *phydev, struct ethtool_ts_info *ti);
417
415 /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */ 418 /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */
416 int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); 419 int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr);
417 420
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 6d6d7d25caaa..a723b1321691 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -17,6 +17,8 @@
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/ethtool.h> 18#include <linux/ethtool.h>
19#include <linux/netdevice.h> 19#include <linux/netdevice.h>
20#include <linux/net_tstamp.h>
21#include <linux/phy.h>
20#include <linux/bitops.h> 22#include <linux/bitops.h>
21#include <linux/uaccess.h> 23#include <linux/uaccess.h>
22#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
@@ -1278,6 +1280,40 @@ out:
1278 return ret; 1280 return ret;
1279} 1281}
1280 1282
1283static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr)
1284{
1285 int err = 0;
1286 struct ethtool_ts_info info;
1287 const struct ethtool_ops *ops = dev->ethtool_ops;
1288 struct phy_device *phydev = dev->phydev;
1289
1290 memset(&info, 0, sizeof(info));
1291 info.cmd = ETHTOOL_GET_TS_INFO;
1292
1293 if (phydev && phydev->drv && phydev->drv->ts_info) {
1294
1295 err = phydev->drv->ts_info(phydev, &info);
1296
1297 } else if (dev->ethtool_ops && dev->ethtool_ops->get_ts_info) {
1298
1299 err = ops->get_ts_info(dev, &info);
1300
1301 } else {
1302 info.so_timestamping =
1303 SOF_TIMESTAMPING_RX_SOFTWARE |
1304 SOF_TIMESTAMPING_SOFTWARE;
1305 info.phc_index = -1;
1306 }
1307
1308 if (err)
1309 return err;
1310
1311 if (copy_to_user(useraddr, &info, sizeof(info)))
1312 err = -EFAULT;
1313
1314 return err;
1315}
1316
1281/* The main entry point in this file. Called from net/core/dev.c */ 1317/* The main entry point in this file. Called from net/core/dev.c */
1282 1318
1283int dev_ethtool(struct net *net, struct ifreq *ifr) 1319int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -1295,11 +1331,13 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1295 return -EFAULT; 1331 return -EFAULT;
1296 1332
1297 if (!dev->ethtool_ops) { 1333 if (!dev->ethtool_ops) {
1298 /* ETHTOOL_GDRVINFO does not require any driver support. 1334 /* A few commands do not require any driver support,
1299 * It is also unprivileged and does not change anything, 1335 * are unprivileged, and do not change anything, so we
1300 * so we can take a shortcut to it. */ 1336 * can take a shortcut to them. */
1301 if (ethcmd == ETHTOOL_GDRVINFO) 1337 if (ethcmd == ETHTOOL_GDRVINFO)
1302 return ethtool_get_drvinfo(dev, useraddr); 1338 return ethtool_get_drvinfo(dev, useraddr);
1339 else if (ethcmd == ETHTOOL_GET_TS_INFO)
1340 return ethtool_get_ts_info(dev, useraddr);
1303 else 1341 else
1304 return -EOPNOTSUPP; 1342 return -EOPNOTSUPP;
1305 } 1343 }
@@ -1330,6 +1368,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1330 case ETHTOOL_GRXCLSRULE: 1368 case ETHTOOL_GRXCLSRULE:
1331 case ETHTOOL_GRXCLSRLALL: 1369 case ETHTOOL_GRXCLSRLALL:
1332 case ETHTOOL_GFEATURES: 1370 case ETHTOOL_GFEATURES:
1371 case ETHTOOL_GET_TS_INFO:
1333 break; 1372 break;
1334 default: 1373 default:
1335 if (!capable(CAP_NET_ADMIN)) 1374 if (!capable(CAP_NET_ADMIN))
@@ -1496,6 +1535,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1496 case ETHTOOL_GET_DUMP_DATA: 1535 case ETHTOOL_GET_DUMP_DATA:
1497 rc = ethtool_get_dump_data(dev, useraddr); 1536 rc = ethtool_get_dump_data(dev, useraddr);
1498 break; 1537 break;
1538 case ETHTOOL_GET_TS_INFO:
1539 rc = ethtool_get_ts_info(dev, useraddr);
1540 break;
1499 default: 1541 default:
1500 rc = -EOPNOTSUPP; 1542 rc = -EOPNOTSUPP;
1501 } 1543 }