diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev_ioctl.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 3730945ee294..10c0e173b38b 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -254,11 +254,32 @@ static int dev_eth_ioctl(struct net_device *dev, static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr) { - return dev_eth_ioctl(dev, ifr, SIOCGHWTSTAMP); + const struct net_device_ops *ops = dev->netdev_ops; + struct kernel_hwtstamp_config kernel_cfg = {}; + struct hwtstamp_config cfg; + int err; + + if (!ops->ndo_hwtstamp_get) + return dev_eth_ioctl(dev, ifr, SIOCGHWTSTAMP); /* legacy */ + + if (!netif_device_present(dev)) + return -ENODEV; + + err = ops->ndo_hwtstamp_get(dev, &kernel_cfg); + if (err) + return err; + + hwtstamp_config_from_kernel(&cfg, &kernel_cfg); + + if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) + return -EFAULT; + + return 0; } static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr) { + const struct net_device_ops *ops = dev->netdev_ops; struct kernel_hwtstamp_config kernel_cfg; struct netlink_ext_ack extack = {}; struct hwtstamp_config cfg; @@ -280,7 +301,28 @@ static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr) return err; } - return dev_eth_ioctl(dev, ifr, SIOCSHWTSTAMP); + if (!ops->ndo_hwtstamp_set) + return dev_eth_ioctl(dev, ifr, SIOCSHWTSTAMP); /* legacy */ + + if (!netif_device_present(dev)) + return -ENODEV; + + err = ops->ndo_hwtstamp_set(dev, &kernel_cfg, &extack); + if (err) { + if (extack._msg) + netdev_err(dev, "%s\n", extack._msg); + return err; + } + + /* The driver may have modified the configuration, so copy the + * updated version of it back to user space + */ + hwtstamp_config_from_kernel(&cfg, &kernel_cfg); + + if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) + return -EFAULT; + + return 0; } static int dev_siocbond(struct net_device *dev, |