Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a633ac2 authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller
Browse files

tg3: PTP - Add the hardware timestamp ioctl



This patch implements the SIOCSHWTSTAMP ioctl as described in
Documentation/networking/timestamping.txt

[Removed HWTSTAMP_FILTER_ALL handling by returning -ERANGE based on input
 from Richard Cochran.]

Signed-off-by: default avatarNithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d41e49a
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
@@ -12760,6 +12760,96 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,

}

static int tg3_hwtstamp_ioctl(struct net_device *dev,
			      struct ifreq *ifr, int cmd)
{
	struct tg3 *tp = netdev_priv(dev);
	struct hwtstamp_config stmpconf;

	if (!tg3_flag(tp, PTP_CAPABLE))
		return -EINVAL;

	if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
		return -EFAULT;

	if (stmpconf.flags)
		return -EINVAL;

	switch (stmpconf.tx_type) {
	case HWTSTAMP_TX_ON:
		tg3_flag_set(tp, TX_TSTAMP_EN);
		break;
	case HWTSTAMP_TX_OFF:
		tg3_flag_clear(tp, TX_TSTAMP_EN);
		break;
	default:
		return -ERANGE;
	}

	switch (stmpconf.rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		tp->rxptpctl = 0;
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
			       TG3_RX_PTP_CTL_ALL_V1_EVENTS;
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
			       TG3_RX_PTP_CTL_SYNC_EVNT;
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
			       TG3_RX_PTP_CTL_DELAY_REQ;
		break;
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
			       TG3_RX_PTP_CTL_ALL_V2_EVENTS;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
			       TG3_RX_PTP_CTL_ALL_V2_EVENTS;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
			       TG3_RX_PTP_CTL_ALL_V2_EVENTS;
		break;
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
			       TG3_RX_PTP_CTL_SYNC_EVNT;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
			       TG3_RX_PTP_CTL_SYNC_EVNT;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
			       TG3_RX_PTP_CTL_SYNC_EVNT;
		break;
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
			       TG3_RX_PTP_CTL_DELAY_REQ;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
			       TG3_RX_PTP_CTL_DELAY_REQ;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
		tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
			       TG3_RX_PTP_CTL_DELAY_REQ;
		break;
	default:
		return -ERANGE;
	}

	if (netif_running(dev) && tp->rxptpctl)
		tw32(TG3_RX_PTP_CTL,
		     tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);

	return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
		-EFAULT : 0;
}

static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct mii_ioctl_data *data = if_mii(ifr);
@@ -12810,6 +12900,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)

		return err;

	case SIOCSHWTSTAMP:
		return tg3_hwtstamp_ioctl(dev, ifr, cmd);

	default:
		/* do nothing */
		break;