diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2013-11-18 17:59:43 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2013-11-21 12:17:36 -0500 |
commit | 7260899bde50cbe84bdf0a15b5642e2c3b03db32 (patch) | |
tree | 68fb5362d9ae2490697f1df017f2d82ecd8b3505 /drivers/net/ethernet/broadcom/tg3.c | |
parent | 7575c917cf29824b71c4dff8274fe39fc32bc173 (diff) |
tg3: Implement the SIOCGHWTSTAMP ioctl
While we're doing this, fix the error code for SIOCSHWTSTAMP ioctl on
non-timestamping hardware.
Compile-tested only.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/broadcom/tg3.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a9e068423ba0..539c6ace1706 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -13603,14 +13603,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
13603 | 13603 | ||
13604 | } | 13604 | } |
13605 | 13605 | ||
13606 | static int tg3_hwtstamp_ioctl(struct net_device *dev, | 13606 | static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) |
13607 | struct ifreq *ifr, int cmd) | ||
13608 | { | 13607 | { |
13609 | struct tg3 *tp = netdev_priv(dev); | 13608 | struct tg3 *tp = netdev_priv(dev); |
13610 | struct hwtstamp_config stmpconf; | 13609 | struct hwtstamp_config stmpconf; |
13611 | 13610 | ||
13612 | if (!tg3_flag(tp, PTP_CAPABLE)) | 13611 | if (!tg3_flag(tp, PTP_CAPABLE)) |
13613 | return -EINVAL; | 13612 | return -EOPNOTSUPP; |
13614 | 13613 | ||
13615 | if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) | 13614 | if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) |
13616 | return -EFAULT; | 13615 | return -EFAULT; |
@@ -13691,6 +13690,67 @@ static int tg3_hwtstamp_ioctl(struct net_device *dev, | |||
13691 | -EFAULT : 0; | 13690 | -EFAULT : 0; |
13692 | } | 13691 | } |
13693 | 13692 | ||
13693 | static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) | ||
13694 | { | ||
13695 | struct tg3 *tp = netdev_priv(dev); | ||
13696 | struct hwtstamp_config stmpconf; | ||
13697 | |||
13698 | if (!tg3_flag(tp, PTP_CAPABLE)) | ||
13699 | return -EOPNOTSUPP; | ||
13700 | |||
13701 | stmpconf.flags = 0; | ||
13702 | stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ? | ||
13703 | HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF); | ||
13704 | |||
13705 | switch (tp->rxptpctl) { | ||
13706 | case 0: | ||
13707 | stmpconf.rx_filter = HWTSTAMP_FILTER_NONE; | ||
13708 | break; | ||
13709 | case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS: | ||
13710 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; | ||
13711 | break; | ||
13712 | case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||
13713 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; | ||
13714 | break; | ||
13715 | case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||
13716 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; | ||
13717 | break; | ||
13718 | case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: | ||
13719 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; | ||
13720 | break; | ||
13721 | case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: | ||
13722 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; | ||
13723 | break; | ||
13724 | case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: | ||
13725 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; | ||
13726 | break; | ||
13727 | case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||
13728 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; | ||
13729 | break; | ||
13730 | case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||
13731 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC; | ||
13732 | break; | ||
13733 | case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||
13734 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; | ||
13735 | break; | ||
13736 | case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||
13737 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; | ||
13738 | break; | ||
13739 | case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||
13740 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ; | ||
13741 | break; | ||
13742 | case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||
13743 | stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; | ||
13744 | break; | ||
13745 | default: | ||
13746 | WARN_ON_ONCE(1); | ||
13747 | return -ERANGE; | ||
13748 | } | ||
13749 | |||
13750 | return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? | ||
13751 | -EFAULT : 0; | ||
13752 | } | ||
13753 | |||
13694 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 13754 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
13695 | { | 13755 | { |
13696 | struct mii_ioctl_data *data = if_mii(ifr); | 13756 | struct mii_ioctl_data *data = if_mii(ifr); |
@@ -13744,7 +13804,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
13744 | return err; | 13804 | return err; |
13745 | 13805 | ||
13746 | case SIOCSHWTSTAMP: | 13806 | case SIOCSHWTSTAMP: |
13747 | return tg3_hwtstamp_ioctl(dev, ifr, cmd); | 13807 | return tg3_hwtstamp_set(dev, ifr); |
13808 | |||
13809 | case SIOCGHWTSTAMP: | ||
13810 | return tg3_hwtstamp_get(dev, ifr); | ||
13748 | 13811 | ||
13749 | default: | 13812 | default: |
13750 | /* do nothing */ | 13813 | /* do nothing */ |