Commit 0f375d90 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Tony Nguyen says:

====================
ice, iavf: Add support for Rx timestamping

Mateusz Polchlopek says:

Initially, during VF creation it registers the PTP clock in
the system and negotiates with PF it's capabilities. In the
meantime the PF enables the Flexible Descriptor for VF.
Only this type of descriptor allows to receive Rx timestamps.

Enabling virtual clock would be possible, though it would probably
perform poorly due to the lack of direct time access.

Enable timestamping should be done using userspace tools, e.g.
hwstamp_ctl -i $VF -r 14

In order to report the timestamps to userspace, the VF extends
timestamp to 40b.

To support this feature the flexible descriptors and PTP part
in iavf driver have been introduced.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  iavf: add support for Rx timestamps to hotpath
  iavf: handle set and get timestamps ops
  iavf: Implement checking DD desc field
  iavf: refactor iavf_clean_rx_irq to support legacy and flex descriptors
  iavf: define Rx descriptors as qwords
  libeth: move idpf_rx_csum_decoded and idpf_rx_extracted
  iavf: periodically cache PHC time
  iavf: add support for indirect access to PHC time
  iavf: add initial framework for registering PTP clock
  iavf: negotiate PTP capabilities
  iavf: add support for negotiating flexible RXDID format
  virtchnl: add enumeration for the rxdid format
  ice: support Rx timestamp on flex descriptor
  virtchnl: add support for enabling PTP on iAVF
====================

Link: https://patch.msgid.link/20250214192739.1175740-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b0b0f520 48ccdcd8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -264,6 +264,7 @@ config I40EVF
	tristate "Intel(R) Ethernet Adaptive Virtual Function support"
	select IAVF
	depends on PCI_MSI
	depends on PTP_1588_CLOCK_OPTIONAL
	help
	  This driver supports virtual functions for Intel XL710,
	  X710, X722, XXV710, and all devices advertising support for
+2 −0
Original line number Diff line number Diff line
@@ -13,3 +13,5 @@ obj-$(CONFIG_IAVF) += iavf.o

iavf-y := iavf_main.o iavf_ethtool.o iavf_virtchnl.o iavf_fdir.o \
	  iavf_adv_rss.o iavf_txrx.o iavf_common.o iavf_adminq.o

iavf-$(CONFIG_PTP_1588_CLOCK) += iavf_ptp.o
+33 −2
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include "iavf_txrx.h"
#include "iavf_fdir.h"
#include "iavf_adv_rss.h"
#include "iavf_types.h"
#include <linux/bitmap.h>

#define DEFAULT_DEBUG_LEVEL_SHIFT 3
@@ -82,7 +83,7 @@ struct iavf_vsi {

#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)

#define IAVF_RX_DESC(R, i) (&(((union iavf_32byte_rx_desc *)((R)->desc))[i]))
#define IAVF_RX_DESC(R, i) (&(((struct iavf_rx_desc *)((R)->desc))[i]))
#define IAVF_TX_DESC(R, i) (&(((struct iavf_tx_desc *)((R)->desc))[i]))
#define IAVF_TX_CTXTDESC(R, i) \
	(&(((struct iavf_tx_context_desc *)((R)->desc))[i]))
@@ -271,6 +272,7 @@ struct iavf_adapter {
	/* Lock to protect accesses to MAC and VLAN lists */
	spinlock_t mac_vlan_list_lock;
	char misc_vector_name[IFNAMSIZ + 9];
	u8 rxdid;
	int num_active_queues;
	int num_req_queues;

@@ -343,6 +345,17 @@ struct iavf_adapter {
#define IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW		BIT_ULL(39)
#define IAVF_FLAG_AQ_CFG_QUEUES_QUANTA_SIZE		BIT_ULL(40)
#define IAVF_FLAG_AQ_GET_QOS_CAPS			BIT_ULL(41)
#define IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS		BIT_ULL(42)
#define IAVF_FLAG_AQ_GET_PTP_CAPS			BIT_ULL(43)
#define IAVF_FLAG_AQ_SEND_PTP_CMD			BIT_ULL(44)

	/* AQ messages that must be sent after IAVF_FLAG_AQ_GET_CONFIG, in
	 * order to negotiated extended capabilities.
	 */
#define IAVF_FLAG_AQ_EXTENDED_CAPS			\
	(IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS |	\
	 IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS |		\
	 IAVF_FLAG_AQ_GET_PTP_CAPS)

	/* flags for processing extended capability messages during
	 * __IAVF_INIT_EXTENDED_CAPS. Each capability exchange requires
@@ -354,10 +367,18 @@ struct iavf_adapter {
	u64 extended_caps;
#define IAVF_EXTENDED_CAP_SEND_VLAN_V2			BIT_ULL(0)
#define IAVF_EXTENDED_CAP_RECV_VLAN_V2			BIT_ULL(1)
#define IAVF_EXTENDED_CAP_SEND_RXDID			BIT_ULL(2)
#define IAVF_EXTENDED_CAP_RECV_RXDID			BIT_ULL(3)
#define IAVF_EXTENDED_CAP_SEND_PTP			BIT_ULL(4)
#define IAVF_EXTENDED_CAP_RECV_PTP			BIT_ULL(5)

#define IAVF_EXTENDED_CAPS				\
	(IAVF_EXTENDED_CAP_SEND_VLAN_V2 |		\
	 IAVF_EXTENDED_CAP_RECV_VLAN_V2)
	 IAVF_EXTENDED_CAP_RECV_VLAN_V2 |		\
	 IAVF_EXTENDED_CAP_SEND_RXDID |			\
	 IAVF_EXTENDED_CAP_RECV_RXDID |			\
	 IAVF_EXTENDED_CAP_SEND_PTP |			\
	 IAVF_EXTENDED_CAP_RECV_PTP)

	/* Lock to prevent possible clobbering of
	 * current_netdev_promisc_flags
@@ -417,12 +438,18 @@ struct iavf_adapter {
			     VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF)
#define QOS_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
			 VIRTCHNL_VF_OFFLOAD_QOS)
#define IAVF_RXDID_ALLOWED(a)						\
	((a)->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)
#define IAVF_PTP_ALLOWED(a)						\
	((a)->vf_res->vf_cap_flags & VIRTCHNL_VF_CAP_PTP)
	struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
	struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
	struct virtchnl_version_info pf_version;
#define PF_IS_V11(_a) (((_a)->pf_version.major == 1) && \
		       ((_a)->pf_version.minor == 1))
	struct virtchnl_vlan_caps vlan_v2_caps;
	u64 supp_rxdids;
	struct iavf_ptp ptp;
	u16 msg_enable;
	struct iavf_eth_stats current_stats;
	struct virtchnl_qos_cap_list *qos_caps;
@@ -555,6 +582,10 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter);
int iavf_get_vf_config(struct iavf_adapter *adapter);
int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter);
int iavf_send_vf_offload_vlan_v2_msg(struct iavf_adapter *adapter);
int iavf_send_vf_supported_rxdids_msg(struct iavf_adapter *adapter);
int iavf_get_vf_supported_rxdids(struct iavf_adapter *adapter);
int iavf_send_vf_ptp_caps_msg(struct iavf_adapter *adapter);
int iavf_get_vf_ptp_caps(struct iavf_adapter *adapter);
void iavf_set_queue_vlan_tag_loc(struct iavf_adapter *adapter);
u16 iavf_get_num_vlans_added(struct iavf_adapter *adapter);
void iavf_irq_enable(struct iavf_adapter *adapter, bool flush);
+219 −9
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <linux/net/intel/libie/rx.h>

#include "iavf.h"
#include "iavf_ptp.h"
#include "iavf_prototype.h"
/* All iavf tracepoints are defined by the include below, which must
 * be included exactly once across the whole kernel with
@@ -709,6 +710,47 @@ static void iavf_configure_tx(struct iavf_adapter *adapter)
		adapter->tx_rings[i].tail = hw->hw_addr + IAVF_QTX_TAIL1(i);
}

/**
 * iavf_select_rx_desc_format - Select Rx descriptor format
 * @adapter: adapter private structure
 *
 * Select what Rx descriptor format based on availability and enabled
 * features.
 *
 * Return: the desired RXDID to select for a given Rx queue, as defined by
 *         enum virtchnl_rxdid_format.
 */
static u8 iavf_select_rx_desc_format(const struct iavf_adapter *adapter)
{
	u64 rxdids = adapter->supp_rxdids;

	/* If we did not negotiate VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC, we must
	 * stick with the default value of the legacy 32 byte format.
	 */
	if (!IAVF_RXDID_ALLOWED(adapter))
		return VIRTCHNL_RXDID_1_32B_BASE;

	/* Rx timestamping requires the use of flexible NIC descriptors */
	if (iavf_ptp_cap_supported(adapter, VIRTCHNL_1588_PTP_CAP_RX_TSTAMP)) {
		if (rxdids & BIT(VIRTCHNL_RXDID_2_FLEX_SQ_NIC))
			return VIRTCHNL_RXDID_2_FLEX_SQ_NIC;

		pci_warn(adapter->pdev,
			 "Unable to negotiate flexible descriptor format\n");
	}

	/* Warn if the PF does not list support for the default legacy
	 * descriptor format. This shouldn't happen, as this is the format
	 * used if VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC is not supported. It is
	 * likely caused by a bug in the PF implementation failing to indicate
	 * support for the format.
	 */
	if (!(rxdids & VIRTCHNL_RXDID_1_32B_BASE_M))
		netdev_warn(adapter->netdev, "PF does not list support for default Rx descriptor format\n");

	return VIRTCHNL_RXDID_1_32B_BASE;
}

/**
 * iavf_configure_rx - Configure Receive Unit after Reset
 * @adapter: board private structure
@@ -719,8 +761,12 @@ static void iavf_configure_rx(struct iavf_adapter *adapter)
{
	struct iavf_hw *hw = &adapter->hw;

	for (u32 i = 0; i < adapter->num_active_queues; i++)
	adapter->rxdid = iavf_select_rx_desc_format(adapter);

	for (u32 i = 0; i < adapter->num_active_queues; i++) {
		adapter->rx_rings[i].tail = hw->hw_addr + IAVF_QRX_TAIL1(i);
		adapter->rx_rings[i].rxdid = adapter->rxdid;
	}
}

/**
@@ -2071,6 +2117,10 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
		return iavf_send_vf_config_msg(adapter);
	if (adapter->aq_required & IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS)
		return iavf_send_vf_offload_vlan_v2_msg(adapter);
	if (adapter->aq_required & IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS)
		return iavf_send_vf_supported_rxdids_msg(adapter);
	if (adapter->aq_required & IAVF_FLAG_AQ_GET_PTP_CAPS)
		return iavf_send_vf_ptp_caps_msg(adapter);
	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES) {
		iavf_disable_queues(adapter);
		return 0;
@@ -2235,7 +2285,10 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
		iavf_enable_vlan_insertion_v2(adapter, ETH_P_8021AD);
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_SEND_PTP_CMD) {
		iavf_virtchnl_send_ptp_cmd(adapter);
		return IAVF_SUCCESS;
	}
	if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_STATS) {
		iavf_request_stats(adapter);
		return 0;
@@ -2599,6 +2652,112 @@ static void iavf_init_recv_offload_vlan_v2_caps(struct iavf_adapter *adapter)
	iavf_change_state(adapter, __IAVF_INIT_FAILED);
}

/**
 * iavf_init_send_supported_rxdids - part of querying for supported RXDID
 * formats
 * @adapter: board private structure
 *
 * Function processes send of the request for supported RXDIDs to the PF.
 * Must clear IAVF_EXTENDED_CAP_RECV_RXDID if the message is not sent, e.g.
 * due to the PF not negotiating VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC.
 */
static void iavf_init_send_supported_rxdids(struct iavf_adapter *adapter)
{
	int ret;

	ret = iavf_send_vf_supported_rxdids_msg(adapter);
	if (ret == -EOPNOTSUPP) {
		/* PF does not support VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC. In this
		 * case, we did not send the capability exchange message and
		 * do not expect a response.
		 */
		adapter->extended_caps &= ~IAVF_EXTENDED_CAP_RECV_RXDID;
	}

	/* We sent the message, so move on to the next step */
	adapter->extended_caps &= ~IAVF_EXTENDED_CAP_SEND_RXDID;
}

/**
 * iavf_init_recv_supported_rxdids - part of querying for supported RXDID
 * formats
 * @adapter: board private structure
 *
 * Function processes receipt of the supported RXDIDs message from the PF.
 **/
static void iavf_init_recv_supported_rxdids(struct iavf_adapter *adapter)
{
	int ret;

	memset(&adapter->supp_rxdids, 0, sizeof(adapter->supp_rxdids));

	ret = iavf_get_vf_supported_rxdids(adapter);
	if (ret)
		goto err;

	/* We've processed the PF response to the
	 * VIRTCHNL_OP_GET_SUPPORTED_RXDIDS message we sent previously.
	 */
	adapter->extended_caps &= ~IAVF_EXTENDED_CAP_RECV_RXDID;
	return;

err:
	/* We didn't receive a reply. Make sure we try sending again when
	 * __IAVF_INIT_FAILED attempts to recover.
	 */
	adapter->extended_caps |= IAVF_EXTENDED_CAP_SEND_RXDID;
	iavf_change_state(adapter, __IAVF_INIT_FAILED);
}

/**
 * iavf_init_send_ptp_caps - part of querying for extended PTP capabilities
 * @adapter: board private structure
 *
 * Function processes send of the request for 1588 PTP capabilities to the PF.
 * Must clear IAVF_EXTENDED_CAP_SEND_PTP if the message is not sent, e.g.
 * due to the PF not negotiating VIRTCHNL_VF_PTP_CAP
 */
static void iavf_init_send_ptp_caps(struct iavf_adapter *adapter)
{
	if (iavf_send_vf_ptp_caps_msg(adapter) == -EOPNOTSUPP) {
		/* PF does not support VIRTCHNL_VF_PTP_CAP. In this case, we
		 * did not send the capability exchange message and do not
		 * expect a response.
		 */
		adapter->extended_caps &= ~IAVF_EXTENDED_CAP_RECV_PTP;
	}

	/* We sent the message, so move on to the next step */
	adapter->extended_caps &= ~IAVF_EXTENDED_CAP_SEND_PTP;
}

/**
 * iavf_init_recv_ptp_caps - part of querying for supported PTP capabilities
 * @adapter: board private structure
 *
 * Function processes receipt of the PTP capabilities supported on this VF.
 **/
static void iavf_init_recv_ptp_caps(struct iavf_adapter *adapter)
{
	memset(&adapter->ptp.hw_caps, 0, sizeof(adapter->ptp.hw_caps));

	if (iavf_get_vf_ptp_caps(adapter))
		goto err;

	/* We've processed the PF response to the VIRTCHNL_OP_1588_PTP_GET_CAPS
	 * message we sent previously.
	 */
	adapter->extended_caps &= ~IAVF_EXTENDED_CAP_RECV_PTP;
	return;

err:
	/* We didn't receive a reply. Make sure we try sending again when
	 * __IAVF_INIT_FAILED attempts to recover.
	 */
	adapter->extended_caps |= IAVF_EXTENDED_CAP_SEND_PTP;
	iavf_change_state(adapter, __IAVF_INIT_FAILED);
}

/**
 * iavf_init_process_extended_caps - Part of driver startup
 * @adapter: board private structure
@@ -2623,6 +2782,24 @@ static void iavf_init_process_extended_caps(struct iavf_adapter *adapter)
		return;
	}

	/* Process capability exchange for RXDID formats */
	if (adapter->extended_caps & IAVF_EXTENDED_CAP_SEND_RXDID) {
		iavf_init_send_supported_rxdids(adapter);
		return;
	} else if (adapter->extended_caps & IAVF_EXTENDED_CAP_RECV_RXDID) {
		iavf_init_recv_supported_rxdids(adapter);
		return;
	}

	/* Process capability exchange for PTP features */
	if (adapter->extended_caps & IAVF_EXTENDED_CAP_SEND_PTP) {
		iavf_init_send_ptp_caps(adapter);
		return;
	} else if (adapter->extended_caps & IAVF_EXTENDED_CAP_RECV_PTP) {
		iavf_init_recv_ptp_caps(adapter);
		return;
	}

	/* When we reach here, no further extended capabilities exchanges are
	 * necessary, so we finally transition into __IAVF_INIT_CONFIG_ADAPTER
	 */
@@ -2714,6 +2891,9 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
	if (QOS_ALLOWED(adapter))
		adapter->aq_required |= IAVF_FLAG_AQ_GET_QOS_CAPS;

	/* Setup initial PTP configuration */
	iavf_ptp_init(adapter);

	iavf_schedule_finish_config(adapter);
	return;

@@ -3139,15 +3319,18 @@ static void iavf_reset_task(struct work_struct *work)
	}

	adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG;
	/* always set since VIRTCHNL_OP_GET_VF_RESOURCES has not been
	 * sent/received yet, so VLAN_V2_ALLOWED() cannot is not reliable here,
	 * however the VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS won't be sent until
	 * VIRTCHNL_OP_GET_VF_RESOURCES and VIRTCHNL_VF_OFFLOAD_VLAN_V2 have
	 * been successfully sent and negotiated
	 */
	adapter->aq_required |= IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS;
	adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS;

	/* Certain capabilities require an extended negotiation process using
	 * extra messages that must be processed after getting the VF
	 * configuration. The related checks such as VLAN_V2_ALLOWED() are not
	 * reliable here, since the configuration has not yet been negotiated.
	 *
	 * Always set these flags, since them related VIRTCHNL messages won't
	 * be sent until after VIRTCHNL_OP_GET_VF_RESOURCES.
	 */
	adapter->aq_required |= IAVF_FLAG_AQ_EXTENDED_CAPS;

	spin_lock_bh(&adapter->mac_vlan_list_lock);

	/* Delete filter for the current MAC address, it could have
@@ -4996,6 +5179,25 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
	return iavf_fix_strip_features(adapter, features);
}

static int iavf_hwstamp_get(struct net_device *netdev,
			    struct kernel_hwtstamp_config *config)
{
	struct iavf_adapter *adapter = netdev_priv(netdev);

	*config = adapter->ptp.hwtstamp_config;

	return 0;
}

static int iavf_hwstamp_set(struct net_device *netdev,
			    struct kernel_hwtstamp_config *config,
			    struct netlink_ext_ack *extack)
{
	struct iavf_adapter *adapter = netdev_priv(netdev);

	return iavf_ptp_set_ts_config(adapter, config, extack);
}

static int
iavf_verify_shaper(struct net_shaper_binding *binding,
		   const struct net_shaper *shaper,
@@ -5104,6 +5306,8 @@ static const struct net_device_ops iavf_netdev_ops = {
	.ndo_set_features	= iavf_set_features,
	.ndo_setup_tc		= iavf_setup_tc,
	.net_shaper_ops		= &iavf_shaper_ops,
	.ndo_hwtstamp_get	= iavf_hwstamp_get,
	.ndo_hwtstamp_set	= iavf_hwstamp_set,
};

/**
@@ -5358,6 +5562,10 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	/* Setup the wait queue for indicating virtchannel events */
	init_waitqueue_head(&adapter->vc_waitqueue);

	INIT_LIST_HEAD(&adapter->ptp.aq_cmds);
	init_waitqueue_head(&adapter->ptp.phc_time_waitqueue);
	mutex_init(&adapter->ptp.aq_cmd_lock);

	queue_delayed_work(adapter->wq, &adapter->watchdog_task,
			   msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
	/* Initialization goes on in the work. Do not add more of it below. */
@@ -5514,6 +5722,8 @@ static void iavf_remove(struct pci_dev *pdev)
		msleep(50);
	}

	iavf_ptp_release(adapter);

	iavf_misc_irq_disable(adapter);
	/* Shut down all the garbage mashers on the detention level */
	cancel_work_sync(&adapter->reset_task);
+485 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading