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

Commit beb0dff1 authored by Jacob Keller's avatar Jacob Keller Committed by Jeff Kirsher
Browse files

i40e: enable PTP



New feature: Enable PTP support in the i40e driver.

Change-ID: I6a8e799f582705191f9583afb1b9231a8db96cc8
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarMatthew Vick <matthew.vick@intel.com>
Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 6ff4ef86
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ config IXGBEVF

config I40E
	tristate "Intel(R) Ethernet Controller XL710 Family support"
	select PTP_1588_CLOCK
	depends on PCI
	---help---
	  This driver supports Intel(R) Ethernet Controller XL710 Family of
+1 −0
Original line number Diff line number Diff line
@@ -40,4 +40,5 @@ i40e-objs := i40e_main.o \
	i40e_debugfs.o	\
	i40e_diag.o	\
	i40e_txrx.o	\
	i40e_ptp.o	\
	i40e_virtchnl_pf.o
+26 −0
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@
#include <net/ip6_checksum.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include "i40e_type.h"
#include "i40e_prototype.h"
#include "i40e_virtchnl.h"
@@ -242,6 +245,7 @@ struct i40e_pf {
#define I40E_FLAG_DCB_ENABLED                  (u64)(1 << 20)
#define I40E_FLAG_FDIR_ENABLED                 (u64)(1 << 21)
#define I40E_FLAG_FDIR_ATR_ENABLED             (u64)(1 << 22)
#define I40E_FLAG_PTP                          (u64)(1 << 25)
#define I40E_FLAG_MFP_ENABLED                  (u64)(1 << 26)
#ifdef CONFIG_I40E_VXLAN
#define I40E_FLAG_VXLAN_FILTER_SYNC            (u64)(1 << 27)
@@ -302,6 +306,20 @@ struct i40e_pf {
	u32	fcoe_hmc_filt_num;
	u32	fcoe_hmc_cntx_num;
	struct i40e_filter_control_settings filter_settings;

	struct ptp_clock *ptp_clock;
	struct ptp_clock_info ptp_caps;
	struct sk_buff *ptp_tx_skb;
	struct work_struct ptp_tx_work;
	struct hwtstamp_config tstamp_config;
	unsigned long ptp_tx_start;
	unsigned long last_rx_ptp_check;
	spinlock_t tmreg_lock; /* Used to protect the device time registers. */
	u64 ptp_base_adj;
	u32 tx_hwtstamp_timeouts;
	u32 rx_hwtstamp_cleared;
	bool ptp_tx;
	bool ptp_rx;
};

struct i40e_mac_filter {
@@ -566,4 +584,12 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
				      bool is_vf, bool is_netdev);
void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);

void i40e_ptp_rx_hang(struct i40e_vsi *vsi);
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf);
void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
void i40e_ptp_set_increment(struct i40e_pf *pf);
int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
void i40e_ptp_init(struct i40e_pf *pf);
void i40e_ptp_stop(struct i40e_pf *pf);
#endif /* _I40E_H_ */
+32 −1
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ static struct i40e_stats i40e_gstrings_stats[] = {
	I40E_PF_STAT("rx_oversize", stats.rx_oversize),
	I40E_PF_STAT("rx_jabber", stats.rx_jabber),
	I40E_PF_STAT("VF_admin_queue_requests", vf_aq_requests),
	I40E_PF_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
	I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
};

#define I40E_QUEUE_STATS_LEN(n) \
@@ -748,7 +750,36 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
static int i40e_get_ts_info(struct net_device *dev,
			    struct ethtool_ts_info *info)
{
	return ethtool_op_get_ts_info(dev, info);
	struct i40e_pf *pf = i40e_netdev_to_pf(dev);

	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
				SOF_TIMESTAMPING_RX_SOFTWARE |
				SOF_TIMESTAMPING_SOFTWARE |
				SOF_TIMESTAMPING_TX_HARDWARE |
				SOF_TIMESTAMPING_RX_HARDWARE |
				SOF_TIMESTAMPING_RAW_HARDWARE;

	if (pf->ptp_clock)
		info->phc_index = ptp_clock_index(pf->ptp_clock);
	else
		info->phc_index = -1;

	info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);

	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
			   (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
			   (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
			   (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);

	return 0;
}

static int i40e_link_test(struct net_device *netdev, u64 *data)
+46 −1
Original line number Diff line number Diff line
@@ -1697,6 +1697,27 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
	return 0;
}

/**
 * i40e_ioctl - Access the hwtstamp interface
 * @netdev: network interface device structure
 * @ifr: interface request data
 * @cmd: ioctl command
 **/
int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_pf *pf = np->vsi->back;

	switch (cmd) {
	case SIOCGHWTSTAMP:
		return i40e_ptp_get_ts_config(pf, ifr);
	case SIOCSHWTSTAMP:
		return i40e_ptp_set_ts_config(pf, ifr);
	default:
		return -EOPNOTSUPP;
	}
}

/**
 * i40e_vlan_stripping_enable - Turn on vlan stripping for the VSI
 * @vsi: the vsi being adjusted
@@ -2151,6 +2172,7 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
	tx_ctx.qlen = ring->count;
	tx_ctx.fd_ena = !!(vsi->back->flags & (I40E_FLAG_FDIR_ENABLED |
					       I40E_FLAG_FDIR_ATR_ENABLED));
	tx_ctx.timesync_ena = !!(vsi->back->flags & I40E_FLAG_PTP);

	/* As part of VSI creation/update, FW allocates certain
	 * Tx arbitration queue sets for each TC enabled for
@@ -2488,6 +2510,7 @@ static void i40e_enable_misc_int_causes(struct i40e_hw *hw)
	      I40E_PFINT_ICR0_ENA_GRST_MASK          |
	      I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK |
	      I40E_PFINT_ICR0_ENA_GPIO_MASK          |
	      I40E_PFINT_ICR0_ENA_TIMESYNC_MASK      |
	      I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK  |
	      I40E_PFINT_ICR0_ENA_HMC_ERR_MASK       |
	      I40E_PFINT_ICR0_ENA_VFLR_MASK          |
@@ -2831,6 +2854,18 @@ static irqreturn_t i40e_intr(int irq, void *data)
		dev_info(&pf->pdev->dev, "HMC error interrupt\n");
	}

	if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) {
		u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0);

		if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) {
			ena_mask &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
			i40e_ptp_tx_hwtstamp(pf);
			prttsyn_stat &= ~I40E_PRTTSYN_STAT_0_TXTIME_MASK;
		}

		wr32(hw, I40E_PRTTSYN_STAT_0, prttsyn_stat);
	}

	/* If a critical error is pending we have no choice but to reset the
	 * device.
	 * Report and mask out any remaining unexpected interrupts.
@@ -4304,6 +4339,9 @@ static void i40e_link_event(struct i40e_pf *pf)

	if (pf->vf)
		i40e_vc_notify_link_state(pf);

	if (pf->flags & I40E_FLAG_PTP)
		i40e_ptp_set_increment(pf);
}

/**
@@ -4385,6 +4423,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
	for (i = 0; i < I40E_MAX_VEB; i++)
		if (pf->veb[i])
			i40e_update_veb_stats(pf->veb[i]);

	i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]);
}

/**
@@ -6033,6 +6073,7 @@ static const struct net_device_ops i40e_netdev_ops = {
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= i40e_set_mac,
	.ndo_change_mtu		= i40e_change_mtu,
	.ndo_do_ioctl		= i40e_ioctl,
	.ndo_tx_timeout		= i40e_tx_timeout,
	.ndo_vlan_rx_add_vid	= i40e_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= i40e_vlan_rx_kill_vid,
@@ -7299,6 +7340,8 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
					 ~I40E_PRTDCB_MFLCN_RFCE_MASK);

fc_complete:
	i40e_ptp_init(pf);

	return ret;
}

@@ -7803,6 +7846,8 @@ static void i40e_remove(struct pci_dev *pdev)

	i40e_dbg_pf_exit(pf);

	i40e_ptp_stop(pf);

	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
		i40e_free_vfs(pf);
		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
Loading