diff options
-rw-r--r-- | include/linux/ethtool.h | 28 | ||||
-rw-r--r-- | include/linux/phy.h | 3 | ||||
-rw-r--r-- | net/core/ethtool.c | 48 |
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 | */ | ||
742 | struct 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 | ||
1283 | static 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 | ||
1283 | int dev_ethtool(struct net *net, struct ifreq *ifr) | 1319 | int 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 | } |