Loading drivers/net/ethernet/msm/emac/emac_ptp.c +135 −3 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -338,7 +338,7 @@ static int emac_ptp_sysfs_tstamp_show(struct device *dev, return retval; getnstimeofday(&ts_now); retval = snprintf(buf, count, retval = scnprintf(buf, count, "%12u.%09u tstamp %12u.%08u time-of-day\n", (int)ts.tv_sec, (int)ts.tv_nsec, (int)ts_now.tv_sec, (int)ts_now.tv_nsec); Loading @@ -346,15 +346,147 @@ static int emac_ptp_sysfs_tstamp_show(struct device *dev, return retval; } /* display ethernet mac time as well as the time of the next mac pps pulse */ static int emac_ptp_sysfs_mtnp_show( struct device *dev, struct device_attribute *attr, char *buf) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); int count = PAGE_SIZE; struct timespec ts; int ret; ret = emac_ptp_gettime(&adpt->hw, &ts); if (ret) return ret; return scnprintf(buf, count, "%ld %ld %ld %ld\n", ts.tv_sec, ts.tv_nsec, (ts.tv_nsec != 0) ? ts.tv_sec : ts.tv_sec + 1, NSEC_PER_SEC - ts.tv_nsec); } /* Do a "slam" of a very particular time into the time registers... */ static int emac_ptp_sysfs_slam( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); uint32_t sec = 0; uint32_t nsec = 0; int ret = -EINVAL; if (sscanf(buf, "%u %u", &sec, &nsec) == 2) { struct timespec ts = {sec, nsec}; ret = emac_ptp_settime(&adpt->hw, &ts); if (ret) { pr_err("%s: emac_ptp_settime failed.\n", __func__); return ret; } ret = count; } else pr_err("%s: sscanf failed.\n", __func__); return ret; } /* Do a coarse time ajustment (ie. coarsely adjust (+/-) the time * registers by the passed offset) */ static int emac_ptp_sysfs_cadj( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); int64_t offset = 0; int ret = -EINVAL; if (sscanf(buf, "%lld", &offset) == 1) { struct timespec ts; uint64_t new_offset; uint32_t sec; uint32_t nsec; ret = emac_ptp_gettime(&adpt->hw, &ts); if (ret) { pr_err("%s: emac_ptp_gettime failed.\n", __func__); return ret; } sec = ts.tv_sec; nsec = ts.tv_nsec; new_offset = (((uint64_t) sec * NSEC_PER_SEC) + (uint64_t) nsec) + offset; nsec = do_div(new_offset, NSEC_PER_SEC); sec = new_offset; ts.tv_sec = sec; ts.tv_nsec = nsec; ret = emac_ptp_settime(&adpt->hw, &ts); if (ret) { pr_err("%s: emac_ptp_settime failed.\n", __func__); return ret; } ret = count; } else pr_err("%s: sscanf failed.\n", __func__); return ret; } /* Do a fine time ajustment (ie. have the timestamp registers adjust * themselves by the passed amount). */ static int emac_ptp_sysfs_fadj( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); int64_t offset = 0; int ret = -EINVAL; if (sscanf(buf, "%lld", &offset) == 1) { ret = emac_ptp_adjtime(&adpt->hw, offset); if (ret) { pr_err("%s: emac_ptp_adjtime failed.\n", __func__); return ret; } ret = count; } else { pr_err("%s: sscanf failed.\n", __func__); } return ret; } static DEVICE_ATTR(cmd, 0222, NULL, emac_ptp_sysfs_cmd); static DEVICE_ATTR(tstamp, 0444, emac_ptp_sysfs_tstamp_show, NULL); static DEVICE_ATTR(mtnp, 0444, emac_ptp_sysfs_mtnp_show, NULL); static DEVICE_ATTR(slam, 0222, NULL, emac_ptp_sysfs_slam); static DEVICE_ATTR(cadj, 0222, NULL, emac_ptp_sysfs_cadj); static DEVICE_ATTR(fadj, 0222, NULL, emac_ptp_sysfs_fadj); static void emac_ptp_sysfs_create(struct net_device *netdev) { struct emac_adapter *adpt = netdev_priv(netdev); if (device_create_file(&netdev->dev, &dev_attr_cmd) || device_create_file(&netdev->dev, &dev_attr_tstamp)) device_create_file(&netdev->dev, &dev_attr_tstamp) || device_create_file(&netdev->dev, &dev_attr_mtnp) || device_create_file(&netdev->dev, &dev_attr_slam) || device_create_file(&netdev->dev, &dev_attr_cadj) || device_create_file(&netdev->dev, &dev_attr_fadj)) emac_err(adpt, "emac_ptp: failed to create sysfs files\n"); } Loading Loading
drivers/net/ethernet/msm/emac/emac_ptp.c +135 −3 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -338,7 +338,7 @@ static int emac_ptp_sysfs_tstamp_show(struct device *dev, return retval; getnstimeofday(&ts_now); retval = snprintf(buf, count, retval = scnprintf(buf, count, "%12u.%09u tstamp %12u.%08u time-of-day\n", (int)ts.tv_sec, (int)ts.tv_nsec, (int)ts_now.tv_sec, (int)ts_now.tv_nsec); Loading @@ -346,15 +346,147 @@ static int emac_ptp_sysfs_tstamp_show(struct device *dev, return retval; } /* display ethernet mac time as well as the time of the next mac pps pulse */ static int emac_ptp_sysfs_mtnp_show( struct device *dev, struct device_attribute *attr, char *buf) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); int count = PAGE_SIZE; struct timespec ts; int ret; ret = emac_ptp_gettime(&adpt->hw, &ts); if (ret) return ret; return scnprintf(buf, count, "%ld %ld %ld %ld\n", ts.tv_sec, ts.tv_nsec, (ts.tv_nsec != 0) ? ts.tv_sec : ts.tv_sec + 1, NSEC_PER_SEC - ts.tv_nsec); } /* Do a "slam" of a very particular time into the time registers... */ static int emac_ptp_sysfs_slam( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); uint32_t sec = 0; uint32_t nsec = 0; int ret = -EINVAL; if (sscanf(buf, "%u %u", &sec, &nsec) == 2) { struct timespec ts = {sec, nsec}; ret = emac_ptp_settime(&adpt->hw, &ts); if (ret) { pr_err("%s: emac_ptp_settime failed.\n", __func__); return ret; } ret = count; } else pr_err("%s: sscanf failed.\n", __func__); return ret; } /* Do a coarse time ajustment (ie. coarsely adjust (+/-) the time * registers by the passed offset) */ static int emac_ptp_sysfs_cadj( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); int64_t offset = 0; int ret = -EINVAL; if (sscanf(buf, "%lld", &offset) == 1) { struct timespec ts; uint64_t new_offset; uint32_t sec; uint32_t nsec; ret = emac_ptp_gettime(&adpt->hw, &ts); if (ret) { pr_err("%s: emac_ptp_gettime failed.\n", __func__); return ret; } sec = ts.tv_sec; nsec = ts.tv_nsec; new_offset = (((uint64_t) sec * NSEC_PER_SEC) + (uint64_t) nsec) + offset; nsec = do_div(new_offset, NSEC_PER_SEC); sec = new_offset; ts.tv_sec = sec; ts.tv_nsec = nsec; ret = emac_ptp_settime(&adpt->hw, &ts); if (ret) { pr_err("%s: emac_ptp_settime failed.\n", __func__); return ret; } ret = count; } else pr_err("%s: sscanf failed.\n", __func__); return ret; } /* Do a fine time ajustment (ie. have the timestamp registers adjust * themselves by the passed amount). */ static int emac_ptp_sysfs_fadj( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct emac_adapter *adpt = netdev_priv(to_net_dev(dev)); int64_t offset = 0; int ret = -EINVAL; if (sscanf(buf, "%lld", &offset) == 1) { ret = emac_ptp_adjtime(&adpt->hw, offset); if (ret) { pr_err("%s: emac_ptp_adjtime failed.\n", __func__); return ret; } ret = count; } else { pr_err("%s: sscanf failed.\n", __func__); } return ret; } static DEVICE_ATTR(cmd, 0222, NULL, emac_ptp_sysfs_cmd); static DEVICE_ATTR(tstamp, 0444, emac_ptp_sysfs_tstamp_show, NULL); static DEVICE_ATTR(mtnp, 0444, emac_ptp_sysfs_mtnp_show, NULL); static DEVICE_ATTR(slam, 0222, NULL, emac_ptp_sysfs_slam); static DEVICE_ATTR(cadj, 0222, NULL, emac_ptp_sysfs_cadj); static DEVICE_ATTR(fadj, 0222, NULL, emac_ptp_sysfs_fadj); static void emac_ptp_sysfs_create(struct net_device *netdev) { struct emac_adapter *adpt = netdev_priv(netdev); if (device_create_file(&netdev->dev, &dev_attr_cmd) || device_create_file(&netdev->dev, &dev_attr_tstamp)) device_create_file(&netdev->dev, &dev_attr_tstamp) || device_create_file(&netdev->dev, &dev_attr_mtnp) || device_create_file(&netdev->dev, &dev_attr_slam) || device_create_file(&netdev->dev, &dev_attr_cadj) || device_create_file(&netdev->dev, &dev_attr_fadj)) emac_err(adpt, "emac_ptp: failed to create sysfs files\n"); } Loading