aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Cochran <richardcochran@gmail.com>2012-04-03 18:59:17 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-04 05:28:45 -0400
commitc8f3a8c31069137fe0100e6920558f1a7487ef3c (patch)
tree891303875fcca8c8110c949955b87e1447dbcdfc
parent995a9090b2b7dc734351f3ac0ba8d913ffb87001 (diff)
ethtool: Introduce a method for getting time stamping capabilities.
This commit adds a new ethtool ioctl that exposes the SO_TIMESTAMPING capabilities of a network interface. In addition, user space programs can use this ioctl to discover the PTP Hardware Clock (PHC) device associated with the interface. Since software receive time stamps are handled by the stack, the generic ethtool code can answer the query correctly in case the MAC or PHY drivers lack special time stamping features. Signed-off-by: Richard Cochran <richardcochran@gmail.com> Reviewed-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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 }