Commit 494565a7 authored by Milena Olech's avatar Milena Olech Committed by Tony Nguyen
Browse files

idpf: add support for Rx timestamping



Add Rx timestamp function when the Rx timestamp value is read directly
from the Rx descriptor. In order to extend the Rx timestamp value to 64
bit in hot path, the PHC time is cached in the receive groups.
Add supported Rx timestamp modes.

Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarMilena Olech <milena.olech@intel.com>
Tested-by: default avatarYiFei Zhu <zhuyifei@google.com>
Tested-by: default avatarMina Almasry <almasrymina@google.com>
Tested-by: default avatarSamuel Salin <Samuel.salin@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 1a49cf81
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1327,6 +1327,7 @@ static void idpf_get_timestamp_filters(const struct idpf_vport *vport,
				SOF_TIMESTAMPING_RAW_HARDWARE;

	info->tx_types = BIT(HWTSTAMP_TX_OFF);
	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);

	if (!vport->tx_tstamp_caps ||
	    vport->adapter->ptp->tx_tstamp_access == IDPF_PTP_NONE)
+4 −2
Original line number Diff line number Diff line
@@ -2342,7 +2342,8 @@ static int idpf_hwtstamp_set(struct net_device *netdev,
		return -EPERM;
	}

	if (!idpf_ptp_is_vport_tx_tstamp_ena(vport)) {
	if (!idpf_ptp_is_vport_tx_tstamp_ena(vport) &&
	    !idpf_ptp_is_vport_rx_tstamp_ena(vport)) {
		idpf_vport_ctrl_unlock(netdev);
		return -EOPNOTSUPP;
	}
@@ -2367,7 +2368,8 @@ static int idpf_hwtstamp_get(struct net_device *netdev,
		return -EPERM;
	}

	if (!idpf_ptp_is_vport_tx_tstamp_ena(vport)) {
	if (!idpf_ptp_is_vport_tx_tstamp_ena(vport) &&
	    !idpf_ptp_is_vport_rx_tstamp_ena(vport)) {
		idpf_vport_ctrl_unlock(netdev);
		return 0;
	}
+88 −1
Original line number Diff line number Diff line
@@ -198,12 +198,41 @@ static int idpf_ptp_gettimex64(struct ptp_clock_info *info,
	return 0;
}

/**
 * idpf_ptp_update_phctime_rxq_grp - Update the cached PHC time for a given Rx
 *				     queue group.
 * @grp: receive queue group in which Rx timestamp is enabled
 * @split: Indicates whether the queue model is split or single queue
 * @systime: Cached system time
 */
static void
idpf_ptp_update_phctime_rxq_grp(const struct idpf_rxq_group *grp, bool split,
				u64 systime)
{
	struct idpf_rx_queue *rxq;
	u16 i;

	if (!split) {
		for (i = 0; i < grp->singleq.num_rxq; i++) {
			rxq = grp->singleq.rxqs[i];
			if (rxq)
				WRITE_ONCE(rxq->cached_phc_time, systime);
		}
	} else {
		for (i = 0; i < grp->splitq.num_rxq_sets; i++) {
			rxq = &grp->splitq.rxq_sets[i]->rxq;
			if (rxq)
				WRITE_ONCE(rxq->cached_phc_time, systime);
		}
	}
}

/**
 * idpf_ptp_update_cached_phctime - Update the cached PHC time values
 * @adapter: Driver specific private structure
 *
 * This function updates the system time values which are cached in the adapter
 * structure.
 * structure and the Rx queues.
 *
 * This function must be called periodically to ensure that the cached value
 * is never more than 2 seconds old.
@@ -226,6 +255,21 @@ static int idpf_ptp_update_cached_phctime(struct idpf_adapter *adapter)
	WRITE_ONCE(adapter->ptp->cached_phc_time, systime);
	WRITE_ONCE(adapter->ptp->cached_phc_jiffies, jiffies);

	idpf_for_each_vport(adapter, vport) {
		bool split;

		if (!vport || !vport->rxq_grps)
			continue;

		split = idpf_is_queue_model_split(vport->rxq_model);

		for (u16 i = 0; i < vport->num_rxq_grp; i++) {
			struct idpf_rxq_group *grp = &vport->rxq_grps[i];

			idpf_ptp_update_phctime_rxq_grp(grp, split, systime);
		}
	}

	return 0;
}

@@ -497,6 +541,48 @@ int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
	return 0;
}

/**
 * idpf_ptp_set_rx_tstamp - Enable or disable Rx timestamping
 * @vport: Virtual port structure
 * @rx_filter: Receive timestamp filter
 */
static void idpf_ptp_set_rx_tstamp(struct idpf_vport *vport, int rx_filter)
{
	bool enable = true, splitq;

	splitq = idpf_is_queue_model_split(vport->rxq_model);

	if (rx_filter == HWTSTAMP_FILTER_NONE) {
		enable = false;
		vport->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
	} else {
		vport->tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL;
	}

	for (u16 i = 0; i < vport->num_rxq_grp; i++) {
		struct idpf_rxq_group *grp = &vport->rxq_grps[i];
		struct idpf_rx_queue *rx_queue;
		u16 j, num_rxq;

		if (splitq)
			num_rxq = grp->splitq.num_rxq_sets;
		else
			num_rxq = grp->singleq.num_rxq;

		for (j = 0; j < num_rxq; j++) {
			if (splitq)
				rx_queue = &grp->splitq.rxq_sets[j]->rxq;
			else
				rx_queue = grp->singleq.rxqs[j];

			if (enable)
				idpf_queue_set(PTP, rx_queue);
			else
				idpf_queue_clear(PTP, rx_queue);
		}
	}
}

/**
 * idpf_ptp_set_timestamp_mode - Setup driver for requested timestamp mode
 * @vport: Virtual port structure
@@ -519,6 +605,7 @@ int idpf_ptp_set_timestamp_mode(struct idpf_vport *vport,
	}

	vport->tstamp_config.tx_type = config->tx_type;
	idpf_ptp_set_rx_tstamp(vport, config->rx_filter);
	*config = vport->tstamp_config;

	return 0;
+21 −0
Original line number Diff line number Diff line
@@ -235,6 +235,27 @@ static inline bool idpf_ptp_is_vport_tx_tstamp_ena(struct idpf_vport *vport)
		return true;
}

/**
 * idpf_ptp_is_vport_rx_tstamp_ena - Verify the Rx timestamping enablement for
 *				     a given vport.
 * @vport: Virtual port structure
 *
 * Rx timestamp feature is enabled if the PTP clock for the adapter is created
 * and it is possible to read the value of the device clock. The second
 * assumption comes from the need to extend the Rx timestamp value to 64 bit
 * based on the current device clock time.
 *
 * Return: true if the Rx timestamping is enabled, false otherwise.
 */
static inline bool idpf_ptp_is_vport_rx_tstamp_ena(struct idpf_vport *vport)
{
	if (!vport->adapter->ptp ||
	    vport->adapter->ptp->get_dev_clk_time_access == IDPF_PTP_NONE)
		return false;
	else
		return true;
}

#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
int idpf_ptp_init(struct idpf_adapter *adapter);
void idpf_ptp_release(struct idpf_adapter *adapter);
+30 −0
Original line number Diff line number Diff line
@@ -3170,6 +3170,33 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
	return 0;
}

/**
 * idpf_rx_hwtstamp - check for an RX timestamp and pass up the stack
 * @rxq: pointer to the rx queue that receives the timestamp
 * @rx_desc: pointer to rx descriptor containing timestamp
 * @skb: skb to put timestamp in
 */
static void
idpf_rx_hwtstamp(const struct idpf_rx_queue *rxq,
		 const struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc,
		 struct sk_buff *skb)
{
	u64 cached_time, ts_ns;
	u32 ts_high;

	if (!(rx_desc->ts_low & VIRTCHNL2_RX_FLEX_TSTAMP_VALID))
		return;

	cached_time = READ_ONCE(rxq->cached_phc_time);

	ts_high = le32_to_cpu(rx_desc->ts_high);
	ts_ns = idpf_ptp_tstamp_extend_32b_to_64b(cached_time, ts_high);

	*skb_hwtstamps(skb) = (struct skb_shared_hwtstamps) {
		.hwtstamp = ns_to_ktime(ts_ns),
	};
}

/**
 * idpf_rx_process_skb_fields - Populate skb header fields from Rx descriptor
 * @rxq: Rx descriptor ring packet is being transacted on
@@ -3195,6 +3222,9 @@ idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb,
	/* process RSS/hash */
	idpf_rx_hash(rxq, skb, rx_desc, decoded);

	if (idpf_queue_has(PTP, rxq))
		idpf_rx_hwtstamp(rxq, rx_desc, skb);

	skb->protocol = eth_type_trans(skb, rxq->netdev);
	skb_record_rx_queue(skb, rxq->idx);

Loading