diff options
author | Hangbin Liu <liuhangbin@gmail.com> | 2019-03-20 10:23:33 +0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-03-20 11:04:41 -0700 |
commit | 254c0a2bfedb9e1baf38bd82ca86494d4bc1e0cb (patch) | |
tree | ec307e1e39ade071f3f1b3d14c46da6d1fcaad68 /drivers | |
parent | 1bfe45f4ae81dc961b4bcb2ce6860c4ee1af621a (diff) |
macvlan: pass get_ts_info and SIOC[SG]HWTSTAMP ioctl to real device
Similiar to commit a6111d3c93d0 ("vlan: Pass SIOC[SG]HWTSTAMP ioctls to
real device") and commit 37dd9255b2f6 ("vlan: Pass ethtool get_ts_info
queries to real device."), add MACVlan HW ptp support.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/macvlan.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 0c0f105657d3..4a6be8fab884 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -24,6 +24,7 @@ #include <linux/notifier.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/net_tstamp.h> #include <linux/ethtool.h> #include <linux/if_arp.h> #include <linux/if_vlan.h> @@ -34,6 +35,7 @@ #include <net/rtnetlink.h> #include <net/xfrm.h> #include <linux/netpoll.h> +#include <linux/phy.h> #define MACVLAN_HASH_BITS 8 #define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS) @@ -822,6 +824,30 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct net_device *real_dev = macvlan_dev_real_dev(dev); + const struct net_device_ops *ops = real_dev->netdev_ops; + struct ifreq ifrr; + int err = -EOPNOTSUPP; + + strncpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ); + ifrr.ifr_ifru = ifr->ifr_ifru; + + switch (cmd) { + case SIOCSHWTSTAMP: + case SIOCGHWTSTAMP: + if (netif_device_present(real_dev) && ops->ndo_do_ioctl) + err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd); + break; + } + + if (!err) + ifr->ifr_ifru = ifrr.ifr_ifru; + + return err; +} + /* * macvlan network devices have devices nesting below it and are a special * "super class" of normal network devices; split their locks off into a @@ -1020,6 +1046,26 @@ static int macvlan_ethtool_get_link_ksettings(struct net_device *dev, return __ethtool_get_link_ksettings(vlan->lowerdev, cmd); } +static int macvlan_ethtool_get_ts_info(struct net_device *dev, + struct ethtool_ts_info *info) +{ + struct net_device *real_dev = macvlan_dev_real_dev(dev); + const struct ethtool_ops *ops = real_dev->ethtool_ops; + struct phy_device *phydev = real_dev->phydev; + + if (phydev && phydev->drv && phydev->drv->ts_info) { + return phydev->drv->ts_info(phydev, info); + } else if (ops->get_ts_info) { + return ops->get_ts_info(real_dev, info); + } else { + info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info->phc_index = -1; + } + + return 0; +} + static netdev_features_t macvlan_fix_features(struct net_device *dev, netdev_features_t features) { @@ -1094,6 +1140,7 @@ static const struct ethtool_ops macvlan_ethtool_ops = { .get_link = ethtool_op_get_link, .get_link_ksettings = macvlan_ethtool_get_link_ksettings, .get_drvinfo = macvlan_ethtool_get_drvinfo, + .get_ts_info = macvlan_ethtool_get_ts_info, }; static const struct net_device_ops macvlan_netdev_ops = { @@ -1103,6 +1150,7 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_stop = macvlan_stop, .ndo_start_xmit = macvlan_start_xmit, .ndo_change_mtu = macvlan_change_mtu, + .ndo_do_ioctl = macvlan_do_ioctl, .ndo_fix_features = macvlan_fix_features, .ndo_change_rx_flags = macvlan_change_rx_flags, .ndo_set_mac_address = macvlan_set_mac_address, |