aboutsummaryrefslogtreecommitdiffstats
path: root/net
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 /net
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>
Diffstat (limited to 'net')
-rw-r--r--net/core/ethtool.c48
1 files changed, 45 insertions, 3 deletions
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 }