lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250902105321.5750-3-anton.nadezhdin@intel.com>
Date: Tue,  2 Sep 2025 06:50:24 -0400
From: Anton Nadezhdin <anton.nadezhdin@...el.com>
To: intel-wired-lan@...ts.osuosl.org
Cc: netdev@...r.kernel.org,
	anthony.l.nguyen@...el.com,
	richardcochran@...il.com,
	Milena Olech <milena.olech@...el.com>,
	Anton Nadezhdin <anton.nadezhdin@...el.com>,
	Aleksandr Loktionov <aleksandr.loktionov@...el.com>
Subject: [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping

From: Milena Olech <milena.olech@...el.com>

Currently IDPF supports only mailbox access to PHC operations and
Tx timestamping, however the driver shall also be able to handle direct
access. The difference is that PHC/timestamps actions are performed
directly, through BAR registers, instead of sending a virtchnl message to
CP. Registers offsets are negotiated with the CP during the capabilities
negotiation.

Signed-off-by: Milena Olech <milena.olech@...el.com>
Co-developed-by: Anton Nadezhdin <anton.nadezhdin@...el.com>
Signed-off-by: Anton Nadezhdin <anton.nadezhdin@...el.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@...el.com>
---
 drivers/net/ethernet/intel/idpf/idpf_ptp.c    | 103 ++++++++++++++++-
 drivers/net/ethernet/intel/idpf/idpf_ptp.h    |  45 ++++++--
 drivers/net/ethernet/intel/idpf/idpf_txrx.c   |  85 +++++++++-----
 drivers/net/ethernet/intel/idpf/idpf_txrx.h   |   4 +
 .../net/ethernet/intel/idpf/idpf_virtchnl.c   |   3 +-
 .../ethernet/intel/idpf/idpf_virtchnl_ptp.c   | 108 +++++++-----------
 drivers/net/ethernet/intel/idpf/virtchnl2.h   |   6 +-
 7 files changed, 245 insertions(+), 109 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_ptp.c b/drivers/net/ethernet/intel/idpf/idpf_ptp.c
index b19dbddf95bf..02881f2902ae 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_ptp.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_ptp.c
@@ -746,6 +746,7 @@ u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp)
  * @tx_q: Transmit queue on which the Tx timestamp is requested
  * @skb: The SKB to associate with this timestamp request
  * @idx: Index of the Tx timestamp latch
+ * @params: pointer to tx params struct
  *
  * Request tx timestamp index negotiated during PTP init that will be set into
  * Tx descriptor.
@@ -754,7 +755,7 @@ u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp)
  * -errno otherwise.
  */
 int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
-			u32 *idx)
+			u32 *idx, struct idpf_tx_splitq_params *params)
 {
 	struct idpf_ptp_tx_tstamp *ptp_tx_tstamp;
 	struct list_head *head;
@@ -770,6 +771,13 @@ int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
 
 	ptp_tx_tstamp = list_first_entry(head, struct idpf_ptp_tx_tstamp,
 					 list_member);
+
+	if (xa_is_err(xa_store(&tx_q->ptp_tx_tstamps, params->compl_tag,
+			       ptp_tx_tstamp, GFP_ATOMIC))) {
+		spin_unlock(&tx_q->cached_tstamp_caps->latches_lock);
+		return -ENOBUFS;
+	}
+
 	list_del(&ptp_tx_tstamp->list_member);
 
 	ptp_tx_tstamp->skb = skb_get(skb);
@@ -781,8 +789,98 @@ int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
 	spin_unlock(&tx_q->cached_tstamp_caps->latches_lock);
 
 	*idx = ptp_tx_tstamp->idx;
+	params->ptp_tx_tstamp = ptp_tx_tstamp;
+
+	return 0;
+}
+
+/**
+ * idpf_ptp_update_tstamp_tracker - Update the Tx timestamp tracker based on
+ *				    the skb compatibility.
+ * @caps: Tx timestamp capabilities that monitor the latch status
+ * @skb: skb for which the tstamp value is returned through virtchnl message
+ * @state_before: Current state of the Tx timestamp latch
+ * @state_after: Expected state of the Tx timestamp latch
+ *
+ * Find a proper skb tracker for which the Tx timestamp is received and change
+ * the state to expected value.
+ *
+ * Return: true if the tracker has been found and updated, false otherwise.
+ */
+bool idpf_ptp_update_tstamp_tracker(struct idpf_ptp_vport_tx_tstamp_caps *caps,
+				    struct sk_buff *skb,
+				    enum idpf_ptp_tx_tstamp_state state_before,
+				    enum idpf_ptp_tx_tstamp_state state_after)
+{
+	bool updated = false;
+
+	spin_lock_bh(&caps->status_lock);
+	for (u16 i = 0; i < caps->num_entries; i++) {
+		struct idpf_ptp_tx_tstamp_status *status;
+
+		status = &caps->tx_tstamp_status[i];
+		if (skb == status->skb && status->state == state_before) {
+			status->state = state_after;
+			updated = true;
+			break;
+		}
+	}
+	spin_unlock_bh(&caps->status_lock);
+
+	return updated;
+}
+
+/**
+ * idpf_ptp_get_tx_tstamp - Read the Tx timestamp value
+ * @vport: Virtual port structure
+ * @tx_tstamp: Tx timestamp structure that holds the latch register offsets
+ *
+ * Read the Tx timestamp value directly - through BAR registers - and provide
+ * it back to the skb.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport,
+			   struct idpf_ptp_tx_tstamp *tx_tstamp)
+{
+	struct idpf_ptp_vport_tx_tstamp_caps *tstamp_caps;
+	u32 tstamp_l, tstamp_h, readiness_h, readiness_l;
+	u64 tstamp, readiness_bitmap;
+	int err = 0;
+
+	tstamp_caps = vport->tx_tstamp_caps;
+
+	readiness_l = readl(tstamp_caps->readiness_offset_l);
+	readiness_h = readl(tstamp_caps->readiness_offset_h);
+	readiness_bitmap = (u64)readiness_h << 32 | readiness_l;
+
+	if (unlikely(!(readiness_bitmap & BIT_ULL(tx_tstamp->idx)))) {
+		err = -EIO;
+		dev_err(&vport->adapter->pdev->dev,
+			"Tx timestamp latch %u is not ready for skb %p\n",
+			tx_tstamp->idx, tx_tstamp->skb);
+		goto error;
+	}
+
+	tstamp_l = readl(tx_tstamp->tx_latch_reg_offset_l);
+	tstamp_h = readl(tx_tstamp->tx_latch_reg_offset_h);
+	tstamp = (u64)tstamp_h << 32 | tstamp_l;
+
+	spin_lock(&tstamp_caps->latches_lock);
+	list_del(&tx_tstamp->list_member);
+	idpf_ptp_get_tstamp_value(vport, tstamp, tx_tstamp, false);
+	spin_unlock(&tstamp_caps->latches_lock);
 
 	return 0;
+
+error:
+	consume_skb(tx_tstamp->skb);
+	spin_lock(&tstamp_caps->latches_lock);
+	list_del(&tx_tstamp->list_member);
+	list_add(&tx_tstamp->list_member,
+		 &tstamp_caps->latches_free);
+	spin_unlock(&tstamp_caps->latches_lock);
+	return err;
 }
 
 /**
@@ -957,7 +1055,8 @@ static void idpf_ptp_release_vport_tstamp(struct idpf_vport *vport)
 	struct idpf_ptp_tx_tstamp *ptp_tx_tstamp, *tmp;
 	struct list_head *head;
 
-	cancel_work_sync(&vport->tstamp_task);
+	if (vport->adapter->ptp->tx_tstamp_access == IDPF_PTP_MAILBOX)
+		cancel_work_sync(&vport->tstamp_task);
 
 	/* Remove list with free latches */
 	spin_lock_bh(&vport->tx_tstamp_caps->latches_lock);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_ptp.h b/drivers/net/ethernet/intel/idpf/idpf_ptp.h
index 26cc616f420c..10ba2081e242 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_ptp.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_ptp.h
@@ -132,8 +132,8 @@ struct idpf_ptp_tx_tstamp_status {
  */
 struct idpf_ptp_tx_tstamp {
 	struct list_head list_member;
-	u32 tx_latch_reg_offset_l;
-	u32 tx_latch_reg_offset_h;
+	void __iomem *tx_latch_reg_offset_l;
+	void __iomem *tx_latch_reg_offset_h;
 	struct sk_buff *skb;
 	u64 tstamp;
 	u32 idx;
@@ -141,23 +141,27 @@ struct idpf_ptp_tx_tstamp {
 
 /**
  * struct idpf_ptp_vport_tx_tstamp_caps - Tx timestamp capabilities
- * @vport_id: the vport id
+ * @vport: pointer to the virtual port structure
  * @num_entries: the number of negotiated Tx timestamp entries
  * @tstamp_ns_lo_bit: first bit for nanosecond part of the timestamp
+ * @access: indicates an access to Tx timestamp
  * @latches_lock: the lock to the lists of free/used timestamp indexes
  * @status_lock: the lock to the status tracker
- * @access: indicates an access to Tx timestamp
+ * @readiness_offset_l: Tx tstamp readiness bitmap low offset
+ * @readiness_offset_h: Tx tstamp readiness bitmap high offset
  * @latches_free: the list of the free Tx timestamps latches
  * @latches_in_use: the list of the used Tx timestamps latches
  * @tx_tstamp_status: Tx tstamp status tracker
  */
 struct idpf_ptp_vport_tx_tstamp_caps {
-	u32 vport_id;
+	struct idpf_vport *vport;
 	u16 num_entries;
 	u16 tstamp_ns_lo_bit;
+	bool access:1;
 	spinlock_t latches_lock;
 	spinlock_t status_lock;
-	bool access:1;
+	void __iomem *readiness_offset_l;
+	void __iomem *readiness_offset_h;
 	struct list_head latches_free;
 	struct list_head latches_in_use;
 	struct idpf_ptp_tx_tstamp_status tx_tstamp_status[];
@@ -287,13 +291,22 @@ int idpf_ptp_adj_dev_clk_fine_mb(struct idpf_adapter *adapter, u64 incval);
 int idpf_ptp_adj_dev_clk_time_mb(struct idpf_adapter *adapter, s64 delta);
 int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport);
 int idpf_ptp_get_tx_tstamp_mb(struct idpf_vport *vport);
+int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport,
+			   struct idpf_ptp_tx_tstamp *tx_tstamp);
+int idpf_ptp_get_tstamp_value(struct idpf_vport *vport, u64 tstamp_latch,
+			      struct idpf_ptp_tx_tstamp *ptp_tx_tstamp,
+			      bool update_tracker);
 int idpf_ptp_set_timestamp_mode(struct idpf_vport *vport,
 				struct kernel_hwtstamp_config *config);
 u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp);
 u64 idpf_ptp_tstamp_extend_32b_to_64b(u64 cached_phc_time, u32 in_timestamp);
 int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
-			u32 *idx);
+			u32 *idx, struct idpf_tx_splitq_params *params);
 void idpf_tstamp_task(struct work_struct *work);
+bool idpf_ptp_update_tstamp_tracker(struct idpf_ptp_vport_tx_tstamp_caps *caps,
+				    struct sk_buff *skb,
+				    enum idpf_ptp_tx_tstamp_state state_before,
+				    enum idpf_ptp_tx_tstamp_state state_after);
 #else /* CONFIG_PTP_1588_CLOCK */
 static inline int idpf_ptp_init(struct idpf_adapter *adapter)
 {
@@ -358,6 +371,11 @@ static inline int idpf_ptp_get_tx_tstamp_mb(struct idpf_vport *vport)
 	return -EOPNOTSUPP;
 }
 
+static inline int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int
 idpf_ptp_set_timestamp_mode(struct idpf_vport *vport,
 			    struct kernel_hwtstamp_config *config)
@@ -377,11 +395,22 @@ static inline u64 idpf_ptp_tstamp_extend_32b_to_64b(u64 cached_phc_time,
 }
 
 static inline int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q,
-				      struct sk_buff *skb, u32 *idx)
+				      struct sk_buff *skb, u32 *idx
+				      struct idpf_tx_splitq_params *params)
 {
 	return -EOPNOTSUPP;
 }
 
 static inline void idpf_tstamp_task(struct work_struct *work) { }
+
+static inline bool
+idpf_ptp_update_tstamp_tracker(struct idpf_ptp_vport_tx_tstamp_caps *caps,
+			       struct sk_buff *skb,
+			       enum idpf_ptp_tx_tstamp_state state_before,
+			       enum idpf_ptp_tx_tstamp_state state_after)
+{
+	return false;
+}
+
 #endif /* CONFIG_PTP_1588_CLOCK */
 #endif /* _IDPF_PTP_H */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index c78af4ffa897..a0dd7ab0bb1a 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -947,6 +947,7 @@ static void idpf_txq_group_rel(struct idpf_vport *vport,
 				txq_grp->txqs[j]->refillq = NULL;
 			}
 
+			xa_destroy(&txq_grp->txqs[j]->ptp_tx_tstamps);
 			kfree(txq_grp->txqs[j]);
 			txq_grp->txqs[j] = NULL;
 		}
@@ -1063,9 +1064,12 @@ static int idpf_vport_init_fast_path_txqs(struct idpf_vport *vport,
 					  struct idpf_q_vec_rsrc *rsrc)
 {
 	struct idpf_ptp_vport_tx_tstamp_caps *caps = vport->tx_tstamp_caps;
-	struct work_struct *tstamp_task = &vport->tstamp_task;
+	struct work_struct *tstamp_task = NULL;
 	int k = 0;
 
+	if (vport->adapter->ptp->tx_tstamp_access == IDPF_PTP_MAILBOX)
+		tstamp_task = &vport->tstamp_task;
+
 	vport->txqs = kcalloc(rsrc->num_txq, sizeof(*vport->txqs),
 			      GFP_KERNEL);
 	if (!vport->txqs)
@@ -1370,6 +1374,7 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport,
 			q->tx_min_pkt_len = idpf_get_min_tx_pkt_len(adapter);
 			q->netdev = vport->netdev;
 			q->txq_grp = tx_qgrp;
+			xa_init(&q->ptp_tx_tstamps);
 
 			if (!split) {
 				q->clean_budget = vport->compln_clean_budget;
@@ -1626,34 +1631,54 @@ int idpf_vport_queues_alloc(struct idpf_vport *vport,
  * idpf_tx_read_tstamp - schedule a work to read Tx timestamp value
  * @txq: queue to read the timestamp from
  * @skb: socket buffer to provide Tx timestamp value
+ * @buf_id: completion tag for this packet
  *
  * Schedule a work to read Tx timestamp value generated once the packet is
  * transmitted.
  */
-static void idpf_tx_read_tstamp(struct idpf_tx_queue *txq, struct sk_buff *skb)
+static void idpf_tx_read_tstamp(struct idpf_tx_queue *txq, struct sk_buff *skb,
+				u32 buf_id)
 {
 	struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;
-	struct idpf_ptp_tx_tstamp_status *tx_tstamp_status;
+	struct idpf_ptp_tx_tstamp_status *tx_tstamp_status = NULL;
+	enum idpf_ptp_access access;
+	int err;
 
 	tx_tstamp_caps = txq->cached_tstamp_caps;
-	spin_lock_bh(&tx_tstamp_caps->status_lock);
-
-	for (u32 i = 0; i < tx_tstamp_caps->num_entries; i++) {
-		tx_tstamp_status = &tx_tstamp_caps->tx_tstamp_status[i];
-		if (tx_tstamp_status->state != IDPF_PTP_FREE)
-			continue;
+	access = tx_tstamp_caps->vport->adapter->ptp->tx_tstamp_access;
+	if (access == IDPF_PTP_MAILBOX) {
+		spin_lock(&tx_tstamp_caps->status_lock);
+
+		for (int i = 0; i < tx_tstamp_caps->num_entries; i++) {
+			struct idpf_ptp_tx_tstamp_status *status;
+
+			status = &tx_tstamp_caps->tx_tstamp_status[i];
+			if (status->state == IDPF_PTP_FREE) {
+				tx_tstamp_status = status;
+				tx_tstamp_status->skb = skb;
+				tx_tstamp_status->state = IDPF_PTP_REQUEST;
+				break;
+			}
+		}
 
-		tx_tstamp_status->skb = skb;
-		tx_tstamp_status->state = IDPF_PTP_REQUEST;
+		spin_unlock(&tx_tstamp_caps->status_lock);
+		if (!tx_tstamp_status)
+			return;
 
-		/* Fetch timestamp from completion descriptor through
-		 * virtchnl msg to report to stack.
-		 */
 		queue_work(system_unbound_wq, txq->tstamp_task);
-		break;
-	}
+	} else if (access == IDPF_PTP_DIRECT) {
+		struct idpf_ptp_tx_tstamp *tx_tstamp = xa_load(&txq->ptp_tx_tstamps, buf_id);
 
-	spin_unlock_bh(&tx_tstamp_caps->status_lock);
+		if (tx_tstamp)
+			err = idpf_ptp_get_tx_tstamp(tx_tstamp_caps->vport, tx_tstamp);
+		else
+			err = -EFAULT;
+
+		if (err)
+			pci_dbg(tx_tstamp_caps->vport->adapter->pdev,
+				"Cannot read Tx timestamp %pe\n",
+				ERR_PTR(err));
+	}
 }
 
 #define idpf_tx_splitq_clean_bump_ntc(txq, ntc, desc, buf)	\
@@ -1765,7 +1790,7 @@ static void idpf_tx_clean_bufs(struct idpf_tx_queue *txq, u32 buf_id,
 	tx_buf = &txq->tx_buf[buf_id];
 	if (tx_buf->type == LIBETH_SQE_SKB) {
 		if (skb_shinfo(tx_buf->skb)->tx_flags & SKBTX_IN_PROGRESS)
-			idpf_tx_read_tstamp(txq, tx_buf->skb);
+			idpf_tx_read_tstamp(txq, tx_buf->skb, buf_id);
 
 		libeth_tx_complete(tx_buf, &cp);
 		idpf_post_buf_refill(txq->refillq, buf_id);
@@ -2555,12 +2580,12 @@ netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb)
  * idpf_tx_tstamp - set up context descriptor for hardware timestamp
  * @tx_q: queue to send buffer on
  * @skb: pointer to the SKB we're sending
- * @off: pointer to the offload struct
+ * @params: pointer to tx params struct
  *
  * Return: Positive index number on success, negative otherwise.
  */
 static int idpf_tx_tstamp(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
-			  struct idpf_tx_offload_params *off)
+			  struct idpf_tx_splitq_params *params)
 {
 	int err, idx;
 
@@ -2572,11 +2597,11 @@ static int idpf_tx_tstamp(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
 		return -1;
 
 	/* Tx timestamps cannot be sampled when doing TSO */
-	if (off->tx_flags & IDPF_TX_FLAGS_TSO)
+	if (params->offload.tx_flags & IDPF_TX_FLAGS_TSO)
 		return -1;
 
 	/* Grab an open timestamp slot */
-	err = idpf_ptp_request_ts(tx_q, skb, &idx);
+	err = idpf_ptp_request_ts(tx_q, skb, &idx, params);
 	if (err) {
 		u64_stats_update_begin(&tx_q->stats_sync);
 		u64_stats_inc(&tx_q->q_stats.tstamp_skipped);
@@ -2585,7 +2610,7 @@ static int idpf_tx_tstamp(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
 		return -1;
 	}
 
-	off->tx_flags |= IDPF_TX_FLAGS_TSYN;
+	params->offload.tx_flags |= IDPF_TX_FLAGS_TSYN;
 
 	return idx;
 }
@@ -2607,7 +2632,7 @@ static void idpf_tx_set_tstamp_desc(union idpf_flex_tx_ctx_desc *ctx_desc,
 }
 #else /* CONFIG_PTP_1588_CLOCK */
 static int idpf_tx_tstamp(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
-			  struct idpf_tx_offload_params *off)
+			  struct idpf_tx_offload_params *params)
 {
 	return -1;
 }
@@ -2687,12 +2712,6 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
 		u64_stats_update_end(&tx_q->stats_sync);
 	}
 
-	idx = idpf_tx_tstamp(tx_q, skb, &tx_params.offload);
-	if (idx != -1) {
-		ctx_desc = idpf_tx_splitq_get_ctx_desc(tx_q);
-		idpf_tx_set_tstamp_desc(ctx_desc, idx);
-	}
-
 	if (idpf_queue_has(FLOW_SCH_EN, tx_q)) {
 		struct idpf_sw_queue *refillq = tx_q->refillq;
 
@@ -2741,6 +2760,12 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
 			tx_params.offload.td_cmd |= IDPF_TX_FLEX_DESC_CMD_CS_EN;
 	}
 
+	idx = idpf_tx_tstamp(tx_q, skb, &tx_params);
+	if (idx != -1) {
+		ctx_desc = idpf_tx_splitq_get_ctx_desc(tx_q);
+		idpf_tx_set_tstamp_desc(ctx_desc, idx);
+	}
+
 	first = &tx_q->tx_buf[buf_id];
 	first->skb = skb;
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
index 2a413147707d..02d1f496167c 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -180,6 +180,7 @@ struct idpf_tx_offload_params {
  * @compl_tag: Associated tag for completion
  * @td_tag: Descriptor tunneling tag
  * @offload: Offload parameters
+ * @ptp_tx_tstamp: pointer to Tx timestamp latch struct in use by this packet
  * @prev_ntu: stored TxQ next_to_use in case of rollback
  * @prev_refill_ntc: stored refillq next_to_clean in case of packet rollback
  * @prev_refill_gen: stored refillq generation bit in case of packet rollback
@@ -193,6 +194,7 @@ struct idpf_tx_splitq_params {
 	};
 
 	struct idpf_tx_offload_params offload;
+	struct idpf_ptp_tx_tstamp *ptp_tx_tstamp;
 
 	u16 prev_ntu;
 	u16 prev_refill_ntc;
@@ -607,6 +609,7 @@ libeth_cacheline_set_assert(struct idpf_rx_queue,
  * @xdp_lock: lock for XDP Tx queues sharing
  * @cached_tstamp_caps: Tx timestamp capabilities negotiated with the CP
  * @tstamp_task: Work that handles Tx timestamp read
+ * @ptp_tx_tstamps: XArray for storing Tx timestamps
  * @stats_sync: See struct u64_stats_sync
  * @q_stats: See union idpf_tx_queue_stats
  * @q_id: Queue id
@@ -673,6 +676,7 @@ struct idpf_tx_queue {
 
 	struct idpf_ptp_vport_tx_tstamp_caps *cached_tstamp_caps;
 	struct work_struct *tstamp_task;
+	struct xarray ptp_tx_tstamps;
 
 	struct u64_stats_sync stats_sync;
 	struct idpf_tx_queue_stats q_stats;
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 30e6033ce24b..44a84469b650 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -3373,7 +3373,8 @@ int idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q)
 		return err == -EOPNOTSUPP ? 0 : err;
 	}
 
-	INIT_WORK(&vport->tstamp_task, idpf_tstamp_task);
+	if (vport->adapter->ptp->tx_tstamp_access == IDPF_PTP_MAILBOX)
+		INIT_WORK(&vport->tstamp_task, idpf_tstamp_task);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c
index f85caba92b17..92256e3491d6 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c
@@ -25,6 +25,7 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter)
 				    VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME_MB |
 				    VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK |
 				    VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK_MB |
+				    VIRTCHNL2_CAP_PTP_TX_TSTAMPS |
 				    VIRTCHNL2_CAP_PTP_TX_TSTAMPS_MB)
 	};
 	struct idpf_vc_xn_params xn_params = {
@@ -342,11 +343,12 @@ int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
 		.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC,
 	};
 	enum idpf_ptp_access tstamp_access, get_dev_clk_access;
+	struct idpf_adapter *adapter = vport->adapter;
 	struct idpf_ptp *ptp = vport->adapter->ptp;
 	struct list_head *head;
 	int err = 0, reply_sz;
 	u16 num_latches;
-	u32 size;
+	u32 size, temp;
 
 	if (!ptp)
 		return -EOPNOTSUPP;
@@ -395,9 +397,16 @@ int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
 
 	tstamp_caps->tstamp_ns_lo_bit = rcv_tx_tstamp_caps->tstamp_ns_lo_bit;
 
-	for (u16 i = 0; i < tstamp_caps->num_entries; i++) {
-		__le32 offset_l, offset_h;
+	if (tstamp_access == IDPF_PTP_DIRECT) {
+		temp = le32_to_cpu(rcv_tx_tstamp_caps->readiness_offset_l);
+		tstamp_caps->readiness_offset_l = idpf_get_reg_addr(adapter,
+								    temp);
+		temp = le32_to_cpu(rcv_tx_tstamp_caps->readiness_offset_h);
+		tstamp_caps->readiness_offset_h = idpf_get_reg_addr(adapter,
+								    temp);
+	}
 
+	for (u16 i = 0; i < tstamp_caps->num_entries; i++) {
 		ptp_tx_tstamp = kzalloc(sizeof(*ptp_tx_tstamp), GFP_KERNEL);
 		if (!ptp_tx_tstamp) {
 			err = -ENOMEM;
@@ -409,10 +418,12 @@ int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
 		if (tstamp_access != IDPF_PTP_DIRECT)
 			goto skip_offsets;
 
-		offset_l = tx_tstamp_latch_caps.tx_latch_reg_offset_l;
-		offset_h = tx_tstamp_latch_caps.tx_latch_reg_offset_h;
-		ptp_tx_tstamp->tx_latch_reg_offset_l = le32_to_cpu(offset_l);
-		ptp_tx_tstamp->tx_latch_reg_offset_h = le32_to_cpu(offset_h);
+		temp = le32_to_cpu(tx_tstamp_latch_caps.tx_latch_reg_offset_l);
+		ptp_tx_tstamp->tx_latch_reg_offset_l = idpf_get_reg_addr(adapter,
+									 temp);
+		temp = le32_to_cpu(tx_tstamp_latch_caps.tx_latch_reg_offset_h);
+		ptp_tx_tstamp->tx_latch_reg_offset_h = idpf_get_reg_addr(adapter,
+									 temp);
 
 skip_offsets:
 		ptp_tx_tstamp->idx = tx_tstamp_latch_caps.index;
@@ -423,6 +434,7 @@ int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
 		tstamp_caps->tx_tstamp_status[i].state = IDPF_PTP_FREE;
 	}
 
+	tstamp_caps->vport = vport;
 	vport->tx_tstamp_caps = tstamp_caps;
 	kfree(rcv_tx_tstamp_caps);
 
@@ -442,94 +454,58 @@ int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
 	return err;
 }
 
-/**
- * idpf_ptp_update_tstamp_tracker - Update the Tx timestamp tracker based on
- *				    the skb compatibility.
- * @caps: Tx timestamp capabilities that monitor the latch status
- * @skb: skb for which the tstamp value is returned through virtchnl message
- * @current_state: Current state of the Tx timestamp latch
- * @expected_state: Expected state of the Tx timestamp latch
- *
- * Find a proper skb tracker for which the Tx timestamp is received and change
- * the state to expected value.
- *
- * Return: true if the tracker has been found and updated, false otherwise.
- */
-static bool
-idpf_ptp_update_tstamp_tracker(struct idpf_ptp_vport_tx_tstamp_caps *caps,
-			       struct sk_buff *skb,
-			       enum idpf_ptp_tx_tstamp_state current_state,
-			       enum idpf_ptp_tx_tstamp_state expected_state)
-{
-	bool updated = false;
-
-	spin_lock(&caps->status_lock);
-	for (u16 i = 0; i < caps->num_entries; i++) {
-		struct idpf_ptp_tx_tstamp_status *status;
-
-		status = &caps->tx_tstamp_status[i];
-
-		if (skb == status->skb && status->state == current_state) {
-			status->state = expected_state;
-			updated = true;
-			break;
-		}
-	}
-	spin_unlock(&caps->status_lock);
-
-	return updated;
-}
-
 /**
  * idpf_ptp_get_tstamp_value - Get the Tx timestamp value and provide it
  *			       back to the skb.
  * @vport: Virtual port structure
  * @tstamp_latch: Tx timestamp latch structure fulfilled by the Control Plane
  * @ptp_tx_tstamp: Tx timestamp latch to add to the free list
+ * @update_tracker: Whether to update the timestamp tracker
  *
  * Read the value of the Tx timestamp for a given latch received from the
  * Control Plane, extend it to 64 bit and provide back to the skb.
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int
-idpf_ptp_get_tstamp_value(struct idpf_vport *vport,
-			  struct virtchnl2_ptp_tx_tstamp_latch *tstamp_latch,
-			  struct idpf_ptp_tx_tstamp *ptp_tx_tstamp)
+int idpf_ptp_get_tstamp_value(struct idpf_vport *vport, u64 tstamp_latch,
+			      struct idpf_ptp_tx_tstamp *ptp_tx_tstamp,
+			      bool update_tracker)
 {
 	struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;
 	struct skb_shared_hwtstamps shhwtstamps;
-	bool state_upd = false;
 	u8 tstamp_ns_lo_bit;
+	int err = 0;
 	u64 tstamp;
 
 	tx_tstamp_caps = vport->tx_tstamp_caps;
 	tstamp_ns_lo_bit = tx_tstamp_caps->tstamp_ns_lo_bit;
 
-	ptp_tx_tstamp->tstamp = le64_to_cpu(tstamp_latch->tstamp);
+	ptp_tx_tstamp->tstamp = tstamp_latch;
 	ptp_tx_tstamp->tstamp >>= tstamp_ns_lo_bit;
 
-	state_upd = idpf_ptp_update_tstamp_tracker(tx_tstamp_caps,
-						   ptp_tx_tstamp->skb,
-						   IDPF_PTP_READ_VALUE,
-						   IDPF_PTP_FREE);
-	if (!state_upd)
-		return -EINVAL;
+	if (update_tracker) {
+		if (!idpf_ptp_update_tstamp_tracker(tx_tstamp_caps,
+						    ptp_tx_tstamp->skb,
+						    IDPF_PTP_READ_VALUE,
+						    IDPF_PTP_FREE)) {
+			err = -EINVAL;
+			goto exit;
+		}
+	}
 
 	tstamp = idpf_ptp_extend_ts(vport, ptp_tx_tstamp->tstamp);
 	shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
 	skb_tstamp_tx(ptp_tx_tstamp->skb, &shhwtstamps);
-	consume_skb(ptp_tx_tstamp->skb);
-	ptp_tx_tstamp->skb = NULL;
-
-	list_add(&ptp_tx_tstamp->list_member,
-		 &tx_tstamp_caps->latches_free);
-
 	u64_stats_update_begin(&vport->tstamp_stats.stats_sync);
 	u64_stats_inc(&vport->tstamp_stats.packets);
 	u64_stats_update_end(&vport->tstamp_stats.stats_sync);
 
-	return 0;
+exit:
+	consume_skb(ptp_tx_tstamp->skb);
+	list_add(&ptp_tx_tstamp->list_member,
+		 &tx_tstamp_caps->latches_free);
+
+	return err;
 }
 
 /**
@@ -596,8 +572,8 @@ idpf_ptp_get_tx_tstamp_async_handler(struct idpf_adapter *adapter,
 			if (tstamp_latch.index == tx_tstamp->idx) {
 				list_del(&tx_tstamp->list_member);
 				err = idpf_ptp_get_tstamp_value(tstamp_vport,
-								&tstamp_latch,
-								tx_tstamp);
+								le64_to_cpu(tstamp_latch.tstamp),
+								tx_tstamp, true);
 				if (err)
 					goto unlock;
 
diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h b/drivers/net/ethernet/intel/idpf/virtchnl2.h
index 02ae447cc24a..c43caa3cd115 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -1464,7 +1464,8 @@ VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_ptp_tx_tstamp_latch_caps);
  * @num_latches: Total number of latches
  * @tstamp_ns_lo_bit: First bit for nanosecond part of the timestamp
  * @tstamp_ns_hi_bit: Last bit for nanosecond part of the timestamp
- * @pad: Padding for future tstamp granularity extensions
+ * @readiness_offset_l: Tx tstamp readiness bitmap low register offset
+ * @readiness_offset_h: Tx tstamp readiness bitmap high register offset
  * @tstamp_latches: Capabilities of Tx timestamp entries
  *
  * PF/VF sends this message to negotiate the Tx timestamp latches for each
@@ -1477,7 +1478,8 @@ struct virtchnl2_ptp_get_vport_tx_tstamp_caps {
 	__le16 num_latches;
 	u8 tstamp_ns_lo_bit;
 	u8 tstamp_ns_hi_bit;
-	u8 pad[8];
+	__le32 readiness_offset_l;
+	__le32 readiness_offset_h;
 
 	struct virtchnl2_ptp_tx_tstamp_latch_caps tstamp_latches[]
 						  __counted_by_le(num_latches);
-- 
2.42.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ