netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iwl-next 0/2] idpf: add direct access for PHC control
@ 2025-09-02 10:50 Anton Nadezhdin
  2025-09-02 10:50 ` [PATCH iwl-next 1/2] idpf: add direct access to discipline the main timer Anton Nadezhdin
  2025-09-02 10:50 ` [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping Anton Nadezhdin
  0 siblings, 2 replies; 6+ messages in thread
From: Anton Nadezhdin @ 2025-09-02 10:50 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: netdev, anthony.l.nguyen, richardcochran, Anton Nadezhdin

IDPF allows to access the clock through virtchnl messages, or directly,
through PCI BAR registers. Registers offsets are negotiated with the
Control Plane during driver initialization process.
This series add support for direct operations to modify the clock as 
well as to read TX timestamp

Milena Olech (2):
  idpf: add direct access to discipline the main timer
  idpf: add direct method for disciplining Tx timestamping

 drivers/net/ethernet/intel/idpf/idpf_dev.c    |   4 +-
 drivers/net/ethernet/intel/idpf/idpf_ptp.c    | 295 +++++++++++++++---
 drivers/net/ethernet/intel/idpf/idpf_ptp.h    | 103 ++++--
 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   | 139 ++++-----
 drivers/net/ethernet/intel/idpf/virtchnl2.h   |   6 +-
 8 files changed, 451 insertions(+), 188 deletions(-)


base-commit: 1235d14de922bc4367c24553bc6b278d56dc3433
-- 
2.42.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH iwl-next 1/2] idpf: add direct access to discipline the main timer
  2025-09-02 10:50 [PATCH iwl-next 0/2] idpf: add direct access for PHC control Anton Nadezhdin
@ 2025-09-02 10:50 ` Anton Nadezhdin
  2025-09-02 11:05   ` Vadim Fedorenko
  2025-09-02 10:50 ` [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping Anton Nadezhdin
  1 sibling, 1 reply; 6+ messages in thread
From: Anton Nadezhdin @ 2025-09-02 10:50 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, richardcochran, Milena Olech,
	Anton Nadezhdin, Aleksandr Loktionov

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

IDPF allows to access the clock through virtchnl messages, or directly,
through PCI BAR registers. Registers offsets are negotiated with the
Control Plane during driver initialization process.
Add support for direct operations to modify the clock.

Signed-off-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Anton Nadezhdin <anton.nadezhdin@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/idpf/idpf_dev.c    |   4 +-
 drivers/net/ethernet/intel/idpf/idpf_ptp.c    | 192 ++++++++++++++----
 drivers/net/ethernet/intel/idpf/idpf_ptp.h    |  60 +++---
 .../ethernet/intel/idpf/idpf_virtchnl_ptp.c   |  31 +--
 4 files changed, 207 insertions(+), 80 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_dev.c
index a4625638cf3f..344975352fad 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
@@ -171,8 +171,8 @@ static void idpf_trigger_reset(struct idpf_adapter *adapter,
  */
 static void idpf_ptp_reg_init(const struct idpf_adapter *adapter)
 {
-	adapter->ptp->cmd.shtime_enable_mask = PF_GLTSYN_CMD_SYNC_SHTIME_EN_M;
-	adapter->ptp->cmd.exec_cmd_mask = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
+	adapter->ptp->cmd.shtime_enable = PF_GLTSYN_CMD_SYNC_SHTIME_EN_M;
+	adapter->ptp->cmd.exec_cmd = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/idpf/idpf_ptp.c b/drivers/net/ethernet/intel/idpf/idpf_ptp.c
index 990e78686786..b19dbddf95bf 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_ptp.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_ptp.c
@@ -80,14 +80,30 @@ static void idpf_ptp_enable_shtime(struct idpf_adapter *adapter)
 	u32 shtime_enable, exec_cmd;
 
 	/* Get offsets */
-	shtime_enable = adapter->ptp->cmd.shtime_enable_mask;
-	exec_cmd = adapter->ptp->cmd.exec_cmd_mask;
+	shtime_enable = adapter->ptp->cmd.shtime_enable;
+	exec_cmd = adapter->ptp->cmd.exec_cmd;
 
 	/* Set the shtime en and the sync field */
 	writel(shtime_enable, adapter->ptp->dev_clk_regs.cmd_sync);
 	writel(exec_cmd | shtime_enable, adapter->ptp->dev_clk_regs.cmd_sync);
 }
 
+/**
+ * idpf_ptp_tmr_cmd - Prepare and trigger a timer sync command
+ * @adapter: Driver specific private structure
+ * @cmd: Command to be executed
+ */
+static void idpf_ptp_tmr_cmd(struct idpf_adapter *adapter, u32 cmd)
+{
+	struct idpf_ptp *ptp = adapter->ptp;
+	u32 exec_cmd = ptp->cmd.exec_cmd;
+
+	writel(cmd, ptp->dev_clk_regs.cmd);
+	writel(cmd, ptp->dev_clk_regs.phy_cmd);
+	writel(exec_cmd, ptp->dev_clk_regs.cmd_sync);
+	writel(0, ptp->dev_clk_regs.cmd);
+}
+
 /**
  * idpf_ptp_read_src_clk_reg_direct - Read directly the main timer value
  * @adapter: Driver specific private structure
@@ -139,7 +155,7 @@ static int idpf_ptp_read_src_clk_reg_mailbox(struct idpf_adapter *adapter,
 	/* Read the system timestamp pre PHC read */
 	ptp_read_system_prets(sts);
 
-	err = idpf_ptp_get_dev_clk_time(adapter, &clk_time);
+	err = idpf_ptp_get_dev_clk_time_mb(adapter, &clk_time);
 	if (err)
 		return err;
 
@@ -223,7 +239,7 @@ static int idpf_ptp_get_sync_device_time_mailbox(struct idpf_adapter *adapter,
 	struct idpf_ptp_dev_timers cross_time;
 	int err;
 
-	err = idpf_ptp_get_cross_time(adapter, &cross_time);
+	err = idpf_ptp_get_cross_time_mb(adapter, &cross_time);
 	if (err)
 		return err;
 
@@ -403,6 +419,33 @@ static int idpf_ptp_update_cached_phctime(struct idpf_adapter *adapter)
 	return 0;
 }
 
+/**
+ * idpf_ptp_set_dev_clk_time_direct- Set the time of the clock directly through
+ *				     BAR registers.
+ * @adapter: Driver specific private structure
+ * @dev_clk_time: Value expressed in nanoseconds to set
+ *
+ * Set the time of the device clock to provided value directly through BAR
+ * registers received during PTP capabilities negotiation.
+ */
+static void idpf_ptp_set_dev_clk_time_direct(struct idpf_adapter *adapter,
+					     u64 dev_clk_time)
+{
+	struct idpf_ptp *ptp = adapter->ptp;
+	u32 dev_clk_time_l, dev_clk_time_h;
+
+	dev_clk_time_l = lower_32_bits(dev_clk_time);
+	dev_clk_time_h = upper_32_bits(dev_clk_time);
+
+	writel(dev_clk_time_l, ptp->dev_clk_regs.dev_clk_ns_l);
+	writel(dev_clk_time_h, ptp->dev_clk_regs.dev_clk_ns_h);
+
+	writel(dev_clk_time_l, ptp->dev_clk_regs.phy_clk_ns_l);
+	writel(dev_clk_time_h, ptp->dev_clk_regs.phy_clk_ns_h);
+
+	idpf_ptp_tmr_cmd(adapter, ptp->cmd.init_time);
+}
+
 /**
  * idpf_ptp_settime64 - Set the time of the clock
  * @info: the driver's PTP info structure
@@ -422,16 +465,20 @@ static int idpf_ptp_settime64(struct ptp_clock_info *info,
 	u64 ns;
 
 	access = adapter->ptp->set_dev_clk_time_access;
-	if (access != IDPF_PTP_MAILBOX)
+	if (access == IDPF_PTP_NONE)
 		return -EOPNOTSUPP;
 
 	ns = timespec64_to_ns(ts);
 
-	err = idpf_ptp_set_dev_clk_time(adapter, ns);
-	if (err) {
-		pci_err(adapter->pdev, "Failed to set the time, err: %pe\n",
-			ERR_PTR(err));
-		return err;
+	if (access == IDPF_PTP_MAILBOX) {
+		err = idpf_ptp_set_dev_clk_time_mb(adapter, ns);
+		if (err) {
+			pci_err(adapter->pdev,
+				"Failed to set the time: %pe\n", ERR_PTR(err));
+			return err;
+		}
+	} else {
+		idpf_ptp_set_dev_clk_time_direct(adapter, ns);
 	}
 
 	err = idpf_ptp_update_cached_phctime(adapter);
@@ -464,6 +511,30 @@ static int idpf_ptp_adjtime_nonatomic(struct ptp_clock_info *info, s64 delta)
 	return idpf_ptp_settime64(info, &now);
 }
 
+/**
+ * idpf_ptp_adj_dev_clk_time_direct - Adjust the time of the clock directly
+ *				      through BAR registers.
+ * @adapter: Driver specific private structure
+ * @delta: Offset in nanoseconds to adjust the time by
+ *
+ * Adjust the time of the clock directly through BAR registers received during
+ * PTP capabilities negotiation.
+ */
+static void idpf_ptp_adj_dev_clk_time_direct(struct idpf_adapter *adapter,
+					     s64 delta)
+{
+	struct idpf_ptp *ptp = adapter->ptp;
+	u32 delta_l = (s32)delta;
+
+	writel(0, ptp->dev_clk_regs.shadj_l);
+	writel(delta_l, ptp->dev_clk_regs.shadj_h);
+
+	writel(0, ptp->dev_clk_regs.phy_shadj_l);
+	writel(delta_l, ptp->dev_clk_regs.phy_shadj_h);
+
+	idpf_ptp_tmr_cmd(adapter, ptp->cmd.adj_time);
+}
+
 /**
  * idpf_ptp_adjtime - Adjust the time of the clock by the indicated delta
  * @info: the driver's PTP info structure
@@ -478,7 +549,7 @@ static int idpf_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
 	int err;
 
 	access = adapter->ptp->adj_dev_clk_time_access;
-	if (access != IDPF_PTP_MAILBOX)
+	if (access == IDPF_PTP_NONE)
 		return -EOPNOTSUPP;
 
 	/* Hardware only supports atomic adjustments using signed 32-bit
@@ -488,11 +559,16 @@ static int idpf_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
 	if (delta > S32_MAX || delta < S32_MIN)
 		return idpf_ptp_adjtime_nonatomic(info, delta);
 
-	err = idpf_ptp_adj_dev_clk_time(adapter, delta);
-	if (err) {
-		pci_err(adapter->pdev, "Failed to adjust the clock with delta %lld err: %pe\n",
-			delta, ERR_PTR(err));
-		return err;
+	if (access == IDPF_PTP_MAILBOX) {
+		err = idpf_ptp_adj_dev_clk_time_mb(adapter, delta);
+		if (err) {
+			pci_err(adapter->pdev,
+				"Failed to adjust the clock with delta %lld err: %pe\n",
+				delta, ERR_PTR(err));
+			return err;
+		}
+	} else {
+		idpf_ptp_adj_dev_clk_time_direct(adapter, delta);
 	}
 
 	err = idpf_ptp_update_cached_phctime(adapter);
@@ -503,6 +579,33 @@ static int idpf_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
 	return 0;
 }
 
+/**
+ * idpf_ptp_adj_dev_clk_fine_direct - Adjust clock increment rate directly
+ *				      through BAR registers.
+ * @adapter: Driver specific private structure
+ * @incval: Source timer increment value per clock cycle
+ *
+ * Adjust clock increment rate directly through BAR registers received during
+ * PTP capabilities negotiation.
+ */
+static void idpf_ptp_adj_dev_clk_fine_direct(struct idpf_adapter *adapter,
+					     u64 incval)
+{
+	struct idpf_ptp *ptp = adapter->ptp;
+	u32 incval_l, incval_h;
+
+	incval_l = lower_32_bits(incval);
+	incval_h = upper_32_bits(incval);
+
+	writel(incval_l, ptp->dev_clk_regs.shadj_l);
+	writel(incval_h, ptp->dev_clk_regs.shadj_h);
+
+	writel(incval_l, ptp->dev_clk_regs.phy_shadj_l);
+	writel(incval_h, ptp->dev_clk_regs.phy_shadj_h);
+
+	idpf_ptp_tmr_cmd(adapter, ptp->cmd.init_incval);
+}
+
 /**
  * idpf_ptp_adjfine - Adjust clock increment rate
  * @info: the driver's PTP info structure
@@ -521,16 +624,22 @@ static int idpf_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
 	int err;
 
 	access = adapter->ptp->adj_dev_clk_time_access;
-	if (access != IDPF_PTP_MAILBOX)
+	if (access == IDPF_PTP_NONE)
 		return -EOPNOTSUPP;
 
 	incval = adapter->ptp->base_incval;
-
 	diff = adjust_by_scaled_ppm(incval, scaled_ppm);
-	err = idpf_ptp_adj_dev_clk_fine(adapter, diff);
-	if (err)
-		pci_err(adapter->pdev, "Failed to adjust clock increment rate for scaled ppm %ld %pe\n",
-			scaled_ppm, ERR_PTR(err));
+
+	if (access == IDPF_PTP_MAILBOX) {
+		err = idpf_ptp_adj_dev_clk_fine_mb(adapter, diff);
+		if (err) {
+			pci_err(adapter->pdev,
+				"Failed to adjust clock increment rate\n");
+			return err;
+		}
+	} else {
+		idpf_ptp_adj_dev_clk_fine_direct(adapter, diff);
+	}
 
 	return 0;
 }
@@ -757,7 +866,7 @@ void idpf_tstamp_task(struct work_struct *work)
 
 	vport = container_of(work, struct idpf_vport, tstamp_task);
 
-	idpf_ptp_get_tx_tstamp(vport);
+	idpf_ptp_get_tx_tstamp_mb(vport);
 }
 
 /**
@@ -928,6 +1037,7 @@ bool idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq)
  */
 int idpf_ptp_init(struct idpf_adapter *adapter)
 {
+	struct idpf_ptp *ptp;
 	struct timespec64 ts;
 	int err;
 
@@ -940,8 +1050,10 @@ int idpf_ptp_init(struct idpf_adapter *adapter)
 	if (!adapter->ptp)
 		return -ENOMEM;
 
+	ptp = adapter->ptp;
+
 	/* add a back pointer to adapter */
-	adapter->ptp->adapter = adapter;
+	ptp->adapter = adapter;
 
 	if (adapter->dev_ops.reg_ops.ptp_reg_init)
 		adapter->dev_ops.reg_ops.ptp_reg_init(adapter);
@@ -951,47 +1063,51 @@ int idpf_ptp_init(struct idpf_adapter *adapter)
 		pci_err(adapter->pdev, "Failed to get PTP caps err %d\n", err);
 		goto free_ptp;
 	}
+	/* Do not initialize the PTP if the device clock time cannot be read. */
+	if (ptp->get_dev_clk_time_access == IDPF_PTP_NONE) {
+		err = -EIO;
+		goto free_ptp;
+	}
 
 	err = idpf_ptp_create_clock(adapter);
 	if (err)
 		goto free_ptp;
-
-	if (adapter->ptp->get_dev_clk_time_access != IDPF_PTP_NONE)
-		ptp_schedule_worker(adapter->ptp->clock, 0);
+	ptp_schedule_worker(ptp->clock, 0);
 
 	/* Write the default increment time value if the clock adjustments
 	 * are enabled.
 	 */
-	if (adapter->ptp->adj_dev_clk_time_access != IDPF_PTP_NONE) {
-		err = idpf_ptp_adj_dev_clk_fine(adapter,
-						adapter->ptp->base_incval);
+	if (ptp->adj_dev_clk_time_access == IDPF_PTP_MAILBOX) {
+		err = idpf_ptp_adj_dev_clk_fine_mb(adapter, ptp->base_incval);
 		if (err)
 			goto remove_clock;
+	} else if (ptp->adj_dev_clk_time_access == IDPF_PTP_DIRECT) {
+		idpf_ptp_adj_dev_clk_fine_direct(adapter, ptp->base_incval);
 	}
 
 	/* Write the initial time value if the set time operation is enabled */
-	if (adapter->ptp->set_dev_clk_time_access != IDPF_PTP_NONE) {
+	if (ptp->set_dev_clk_time_access != IDPF_PTP_NONE) {
 		ts = ktime_to_timespec64(ktime_get_real());
-		err = idpf_ptp_settime64(&adapter->ptp->info, &ts);
+		err = idpf_ptp_settime64(&ptp->info, &ts);
 		if (err)
 			goto remove_clock;
 	}
 
-	spin_lock_init(&adapter->ptp->read_dev_clk_lock);
+	spin_lock_init(&ptp->read_dev_clk_lock);
 
 	pci_dbg(adapter->pdev, "PTP init successful\n");
 
 	return 0;
 
 remove_clock:
-	if (adapter->ptp->get_dev_clk_time_access != IDPF_PTP_NONE)
-		ptp_cancel_worker_sync(adapter->ptp->clock);
+	if (ptp->get_dev_clk_time_access != IDPF_PTP_NONE)
+		ptp_cancel_worker_sync(ptp->clock);
 
-	ptp_clock_unregister(adapter->ptp->clock);
-	adapter->ptp->clock = NULL;
+	ptp_clock_unregister(ptp->clock);
+	ptp->clock = NULL;
 
 free_ptp:
-	kfree(adapter->ptp);
+	kfree(ptp);
 	adapter->ptp = NULL;
 
 	return err;
diff --git a/drivers/net/ethernet/intel/idpf/idpf_ptp.h b/drivers/net/ethernet/intel/idpf/idpf_ptp.h
index 785da03e4cf5..26cc616f420c 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_ptp.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_ptp.h
@@ -7,13 +7,21 @@
 #include <linux/ptp_clock_kernel.h>
 
 /**
- * struct idpf_ptp_cmd - PTP command masks
- * @exec_cmd_mask: mask to trigger command execution
- * @shtime_enable_mask: mask to enable shadow time
+ * struct idpf_ptp_cmd_mask - PTP command masks
+ * @exec_cmd: mask to trigger command execution
+ * @shtime_enable: mask to enable shadow time
+ * @init_time: initialize the device clock timer
+ * @init_incval: initialize increment value
+ * @adj_time: adjust the device clock timer
+ * @read_time: read the device clock timer
  */
-struct idpf_ptp_cmd {
-	u32 exec_cmd_mask;
-	u32 shtime_enable_mask;
+struct idpf_ptp_cmd_mask {
+	u32 exec_cmd;
+	u32 shtime_enable;
+	u32 init_time;
+	u32 init_incval;
+	u32 adj_time;
+	u32 read_time;
 };
 
 /* struct idpf_ptp_dev_clk_regs - PTP device registers
@@ -183,7 +191,7 @@ struct idpf_ptp {
 	struct idpf_adapter *adapter;
 	u64 base_incval;
 	u64 max_adj;
-	struct idpf_ptp_cmd cmd;
+	struct idpf_ptp_cmd_mask cmd;
 	u64 cached_phc_time;
 	unsigned long cached_phc_jiffies;
 	struct idpf_ptp_dev_clk_regs dev_clk_regs;
@@ -270,15 +278,15 @@ void idpf_ptp_release(struct idpf_adapter *adapter);
 int idpf_ptp_get_caps(struct idpf_adapter *adapter);
 void idpf_ptp_get_features_access(const struct idpf_adapter *adapter);
 bool idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq);
-int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
-			      struct idpf_ptp_dev_timers *dev_clk_time);
-int idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
-			    struct idpf_ptp_dev_timers *cross_time);
-int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time);
-int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, u64 incval);
-int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta);
+int idpf_ptp_get_cross_time_mb(struct idpf_adapter *adapter,
+			       struct idpf_ptp_dev_timers *cross_time);
+int idpf_ptp_get_dev_clk_time_mb(struct idpf_adapter *adapter,
+				 struct idpf_ptp_dev_timers *dev_clk_time);
+int idpf_ptp_set_dev_clk_time_mb(struct idpf_adapter *adapter, u64 time);
+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(struct idpf_vport *vport);
+int idpf_ptp_get_tx_tstamp_mb(struct idpf_vport *vport);
 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);
@@ -309,33 +317,33 @@ idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq)
 }
 
 static inline int
-idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
-			  struct idpf_ptp_dev_timers *dev_clk_time)
+idpf_ptp_get_dev_clk_time_mb(struct idpf_adapter *adapter,
+			     struct idpf_ptp_dev_timers *dev_clk_time)
 {
 	return -EOPNOTSUPP;
 }
 
 static inline int
-idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
-			struct idpf_ptp_dev_timers *cross_time)
+idpf_ptp_get_cross_time_mb(struct idpf_adapter *adapter,
+			   struct idpf_ptp_dev_timers *cross_time)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter,
-					    u64 time)
+static inline int idpf_ptp_set_dev_clk_time_mb(struct idpf_adapter *adapter,
+					       u64 time)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter,
-					    u64 incval)
+static inline int idpf_ptp_adj_dev_clk_fine_mb(struct idpf_adapter *adapter,
+					       u64 incval)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter,
-					    s64 delta)
+static inline int idpf_ptp_adj_dev_clk_time_mb(struct idpf_adapter *adapter,
+					       s64 delta)
 {
 	return -EOPNOTSUPP;
 }
@@ -345,7 +353,7 @@ static inline int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
 	return -EOPNOTSUPP;
 }
 
-static inline int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport)
+static inline int idpf_ptp_get_tx_tstamp_mb(struct idpf_vport *vport)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c
index 61cedb6f2854..f85caba92b17 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c
@@ -20,7 +20,10 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter)
 		.caps = cpu_to_le32(VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME |
 				    VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME_MB |
 				    VIRTCHNL2_CAP_PTP_GET_CROSS_TIME |
+				    VIRTCHNL2_CAP_PTP_GET_CROSS_TIME_MB |
+				    VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME |
 				    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_MB)
 	};
@@ -144,7 +147,7 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter)
 }
 
 /**
- * idpf_ptp_get_dev_clk_time - Send virtchnl get device clk time message
+ * idpf_ptp_get_dev_clk_time_mb - Send virtchnl get device clk time message
  * @adapter: Driver specific private structure
  * @dev_clk_time: Pointer to the device clock structure where the value is set
  *
@@ -152,8 +155,8 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter)
  *
  * Return: 0 on success, -errno otherwise.
  */
-int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
-			      struct idpf_ptp_dev_timers *dev_clk_time)
+int idpf_ptp_get_dev_clk_time_mb(struct idpf_adapter *adapter,
+				 struct idpf_ptp_dev_timers *dev_clk_time)
 {
 	struct virtchnl2_ptp_get_dev_clk_time get_dev_clk_time_msg;
 	struct idpf_vc_xn_params xn_params = {
@@ -180,7 +183,7 @@ int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
 }
 
 /**
- * idpf_ptp_get_cross_time - Send virtchnl get cross time message
+ * idpf_ptp_get_cross_time_mb - Send virtchnl get cross time message
  * @adapter: Driver specific private structure
  * @cross_time: Pointer to the device clock structure where the value is set
  *
@@ -189,8 +192,8 @@ int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
  *
  * Return: 0 on success, -errno otherwise.
  */
-int idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
-			    struct idpf_ptp_dev_timers *cross_time)
+int idpf_ptp_get_cross_time_mb(struct idpf_adapter *adapter,
+			       struct idpf_ptp_dev_timers *cross_time)
 {
 	struct virtchnl2_ptp_get_cross_time cross_time_msg;
 	struct idpf_vc_xn_params xn_params = {
@@ -216,7 +219,7 @@ int idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
 }
 
 /**
- * idpf_ptp_set_dev_clk_time - Send virtchnl set device time message
+ * idpf_ptp_set_dev_clk_time_mb - Send virtchnl set device time message
  * @adapter: Driver specific private structure
  * @time: New time value
  *
@@ -224,7 +227,7 @@ int idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
  *
  * Return: 0 on success, -errno otherwise.
  */
-int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time)
+int idpf_ptp_set_dev_clk_time_mb(struct idpf_adapter *adapter, u64 time)
 {
 	struct virtchnl2_ptp_set_dev_clk_time set_dev_clk_time_msg = {
 		.dev_time_ns = cpu_to_le64(time),
@@ -249,7 +252,7 @@ int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time)
 }
 
 /**
- * idpf_ptp_adj_dev_clk_time - Send virtchnl adj device clock time message
+ * idpf_ptp_adj_dev_clk_time_mb - Send virtchnl adj device clock time message
  * @adapter: Driver specific private structure
  * @delta: Offset in nanoseconds to adjust the time by
  *
@@ -257,7 +260,7 @@ int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time)
  *
  * Return: 0 on success, -errno otherwise.
  */
-int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta)
+int idpf_ptp_adj_dev_clk_time_mb(struct idpf_adapter *adapter, s64 delta)
 {
 	struct virtchnl2_ptp_adj_dev_clk_time adj_dev_clk_time_msg = {
 		.delta = cpu_to_le64(delta),
@@ -282,7 +285,7 @@ int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta)
 }
 
 /**
- * idpf_ptp_adj_dev_clk_fine - Send virtchnl adj time message
+ * idpf_ptp_adj_dev_clk_fine_mb - Send virtchnl adj time message
  * @adapter: Driver specific private structure
  * @incval: Source timer increment value per clock cycle
  *
@@ -291,7 +294,7 @@ int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta)
  *
  * Return: 0 on success, -errno otherwise.
  */
-int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, u64 incval)
+int idpf_ptp_adj_dev_clk_fine_mb(struct idpf_adapter *adapter, u64 incval)
 {
 	struct virtchnl2_ptp_adj_dev_clk_fine adj_dev_clk_fine_msg = {
 		.incval = cpu_to_le64(incval),
@@ -610,7 +613,7 @@ idpf_ptp_get_tx_tstamp_async_handler(struct idpf_adapter *adapter,
 }
 
 /**
- * idpf_ptp_get_tx_tstamp - Send virtchnl get Tx timestamp latches message
+ * idpf_ptp_get_tx_tstamp_mb - Send virtchnl get Tx timestamp latches message
  * @vport: Virtual port structure
  *
  * Send virtchnl get Tx tstamp message to read the value of the HW timestamp.
@@ -618,7 +621,7 @@ idpf_ptp_get_tx_tstamp_async_handler(struct idpf_adapter *adapter,
  *
  * Return: 0 on success, -errno otherwise.
  */
-int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport)
+int idpf_ptp_get_tx_tstamp_mb(struct idpf_vport *vport)
 {
 	struct virtchnl2_ptp_get_vport_tx_tstamp_latches *send_tx_tstamp_msg;
 	struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping
  2025-09-02 10:50 [PATCH iwl-next 0/2] idpf: add direct access for PHC control Anton Nadezhdin
  2025-09-02 10:50 ` [PATCH iwl-next 1/2] idpf: add direct access to discipline the main timer Anton Nadezhdin
@ 2025-09-02 10:50 ` Anton Nadezhdin
  2025-09-02 11:27   ` Vadim Fedorenko
  2025-09-02 14:06   ` [Intel-wired-lan] " kernel test robot
  1 sibling, 2 replies; 6+ messages in thread
From: Anton Nadezhdin @ 2025-09-02 10:50 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, richardcochran, Milena Olech,
	Anton Nadezhdin, Aleksandr Loktionov

From: Milena Olech <milena.olech@intel.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@intel.com>
Co-developed-by: Anton Nadezhdin <anton.nadezhdin@intel.com>
Signed-off-by: Anton Nadezhdin <anton.nadezhdin@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH iwl-next 1/2] idpf: add direct access to discipline the main timer
  2025-09-02 10:50 ` [PATCH iwl-next 1/2] idpf: add direct access to discipline the main timer Anton Nadezhdin
@ 2025-09-02 11:05   ` Vadim Fedorenko
  0 siblings, 0 replies; 6+ messages in thread
From: Vadim Fedorenko @ 2025-09-02 11:05 UTC (permalink / raw)
  To: Anton Nadezhdin, intel-wired-lan
  Cc: netdev, anthony.l.nguyen, richardcochran, Milena Olech,
	Aleksandr Loktionov, Jakub Kicinski, Willem de Bruijn

On 02/09/2025 11:50, Anton Nadezhdin wrote:
> From: Milena Olech <milena.olech@intel.com>
> 
> IDPF allows to access the clock through virtchnl messages, or directly,
> through PCI BAR registers. Registers offsets are negotiated with the
> Control Plane during driver initialization process.
> Add support for direct operations to modify the clock.
> 
> Signed-off-by: Milena Olech <milena.olech@intel.com>
> Signed-off-by: Anton Nadezhdin <anton.nadezhdin@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---

[...]

>   static void idpf_ptp_reg_init(const struct idpf_adapter *adapter)
>   {
> -	adapter->ptp->cmd.shtime_enable_mask = PF_GLTSYN_CMD_SYNC_SHTIME_EN_M;
> -	adapter->ptp->cmd.exec_cmd_mask = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
> +	adapter->ptp->cmd.shtime_enable = PF_GLTSYN_CMD_SYNC_SHTIME_EN_M;
> +	adapter->ptp->cmd.exec_cmd = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
>   }

[...]

> +/**
> + * idpf_ptp_set_dev_clk_time_direct- Set the time of the clock directly through
> + *				     BAR registers.
> + * @adapter: Driver specific private structure
> + * @dev_clk_time: Value expressed in nanoseconds to set
> + *
> + * Set the time of the device clock to provided value directly through BAR
> + * registers received during PTP capabilities negotiation.
> + */
> +static void idpf_ptp_set_dev_clk_time_direct(struct idpf_adapter *adapter,
> +					     u64 dev_clk_time)
> +{
> +	struct idpf_ptp *ptp = adapter->ptp;
> +	u32 dev_clk_time_l, dev_clk_time_h;
> +
> +	dev_clk_time_l = lower_32_bits(dev_clk_time);
> +	dev_clk_time_h = upper_32_bits(dev_clk_time);
> +
> +	writel(dev_clk_time_l, ptp->dev_clk_regs.dev_clk_ns_l);
> +	writel(dev_clk_time_h, ptp->dev_clk_regs.dev_clk_ns_h);
> +
> +	writel(dev_clk_time_l, ptp->dev_clk_regs.phy_clk_ns_l);
> +	writel(dev_clk_time_h, ptp->dev_clk_regs.phy_clk_ns_h);
> +
> +	idpf_ptp_tmr_cmd(adapter, ptp->cmd.init_time);
> +}
> +
[...]

> +/**
> + * idpf_ptp_adj_dev_clk_time_direct - Adjust the time of the clock directly
> + *				      through BAR registers.
> + * @adapter: Driver specific private structure
> + * @delta: Offset in nanoseconds to adjust the time by
> + *
> + * Adjust the time of the clock directly through BAR registers received during
> + * PTP capabilities negotiation.
> + */
> +static void idpf_ptp_adj_dev_clk_time_direct(struct idpf_adapter *adapter,
> +					     s64 delta)
> +{
> +	struct idpf_ptp *ptp = adapter->ptp;
> +	u32 delta_l = (s32)delta;
> +
> +	writel(0, ptp->dev_clk_regs.shadj_l);
> +	writel(delta_l, ptp->dev_clk_regs.shadj_h);
> +
> +	writel(0, ptp->dev_clk_regs.phy_shadj_l);
> +	writel(delta_l, ptp->dev_clk_regs.phy_shadj_h);
> +
> +	idpf_ptp_tmr_cmd(adapter, ptp->cmd.adj_time);
> +}

[...]

> - * struct idpf_ptp_cmd - PTP command masks
> - * @exec_cmd_mask: mask to trigger command execution
> - * @shtime_enable_mask: mask to enable shadow time
> + * struct idpf_ptp_cmd_mask - PTP command masks
> + * @exec_cmd: mask to trigger command execution
> + * @shtime_enable: mask to enable shadow time
> + * @init_time: initialize the device clock timer
> + * @init_incval: initialize increment value
> + * @adj_time: adjust the device clock timer
> + * @read_time: read the device clock timer
>    */
> -struct idpf_ptp_cmd {
> -	u32 exec_cmd_mask;
> -	u32 shtime_enable_mask;
> +struct idpf_ptp_cmd_mask {
> +	u32 exec_cmd;
> +	u32 shtime_enable;
> +	u32 init_time;
> +	u32 init_incval;
> +	u32 adj_time;
> +	u32 read_time;
>   };
>   
>   /* struct idpf_ptp_dev_clk_regs - PTP device registers
> @@ -183,7 +191,7 @@ struct idpf_ptp {
>   	struct idpf_adapter *adapter;
>   	u64 base_incval;
>   	u64 max_adj;
> -	struct idpf_ptp_cmd cmd;
> +	struct idpf_ptp_cmd_mask cmd;
>   	u64 cached_phc_time;
For the field cmd you changed the struct definition to add more commands
but this diff doesn't init values for new fields. At the same time these
new fields are used in several new functions (idpf_ptp_*_direct). We end
up using 0 while issuing the command.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping
  2025-09-02 10:50 ` [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping Anton Nadezhdin
@ 2025-09-02 11:27   ` Vadim Fedorenko
  2025-09-02 14:06   ` [Intel-wired-lan] " kernel test robot
  1 sibling, 0 replies; 6+ messages in thread
From: Vadim Fedorenko @ 2025-09-02 11:27 UTC (permalink / raw)
  To: Anton Nadezhdin, intel-wired-lan
  Cc: netdev, anthony.l.nguyen, richardcochran, Milena Olech,
	Aleksandr Loktionov, Jakub Kicinski, Willem de Bruijn

On 02/09/2025 11:50, Anton Nadezhdin wrote:
> From: Milena Olech <milena.olech@intel.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@intel.com>
> Co-developed-by: Anton Nadezhdin <anton.nadezhdin@intel.com>
> Signed-off-by: Anton Nadezhdin <anton.nadezhdin@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>

[...]

> -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;

this breaks reverse x-mass tree aligment...

> +	enum idpf_ptp_access access;
> +	int err;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Intel-wired-lan] [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping
  2025-09-02 10:50 ` [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping Anton Nadezhdin
  2025-09-02 11:27   ` Vadim Fedorenko
@ 2025-09-02 14:06   ` kernel test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kernel test robot @ 2025-09-02 14:06 UTC (permalink / raw)
  To: Anton Nadezhdin, intel-wired-lan
  Cc: oe-kbuild-all, netdev, anthony.l.nguyen, richardcochran,
	Milena Olech, Anton Nadezhdin, Aleksandr Loktionov

Hi Anton,

kernel test robot noticed the following build errors:

[auto build test ERROR on 1235d14de922bc4367c24553bc6b278d56dc3433]

url:    https://github.com/intel-lab-lkp/linux/commits/Anton-Nadezhdin/idpf-add-direct-access-to-discipline-the-main-timer/20250902-170325
base:   1235d14de922bc4367c24553bc6b278d56dc3433
patch link:    https://lore.kernel.org/r/20250902105321.5750-3-anton.nadezhdin%40intel.com
patch subject: [Intel-wired-lan] [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping
config: powerpc-randconfig-002-20250902 (https://download.01.org/0day-ci/archive/20250902/202509022155.uBpemgov-lkp@intel.com/config)
compiler: powerpc-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250902/202509022155.uBpemgov-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509022155.uBpemgov-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/net/ethernet/intel/idpf/idpf_txrx.c:5:
>> drivers/net/ethernet/intel/idpf/idpf_ptp.h:399:11: error: expected ';', ',' or ')' before 'struct'
              struct idpf_tx_splitq_params *params)
              ^~~~~~
   drivers/net/ethernet/intel/idpf/idpf_txrx.c: In function 'idpf_tx_read_tstamp':
>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1673:10: error: too many arguments to function 'idpf_ptp_get_tx_tstamp'
       err = idpf_ptp_get_tx_tstamp(tx_tstamp_caps->vport, tx_tstamp);
             ^~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/net/ethernet/intel/idpf/idpf_txrx.c:5:
   drivers/net/ethernet/intel/idpf/idpf_ptp.h:374:19: note: declared here
    static inline int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport)
                      ^~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/idpf/idpf_txrx.c: In function 'idpf_tx_splitq_frame':
>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:2763:34: error: passing argument 3 of 'idpf_tx_tstamp' from incompatible pointer type [-Werror=incompatible-pointer-types]
     idx = idpf_tx_tstamp(tx_q, skb, &tx_params);
                                     ^~~~~~~~~~
   drivers/net/ethernet/intel/idpf/idpf_txrx.c:2635:37: note: expected 'struct idpf_tx_offload_params *' but argument is of type 'struct idpf_tx_splitq_params *'
         struct idpf_tx_offload_params *params)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
   cc1: some warnings being treated as errors
--
   In file included from drivers/net/ethernet/intel/idpf/idpf_lib.c:6:
>> drivers/net/ethernet/intel/idpf/idpf_ptp.h:399:11: error: expected ';', ',' or ')' before 'struct'
              struct idpf_tx_splitq_params *params)
              ^~~~~~


vim +399 drivers/net/ethernet/intel/idpf/idpf_ptp.h

   396	
   397	static inline int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q,
   398					      struct sk_buff *skb, u32 *idx
 > 399					      struct idpf_tx_splitq_params *params)
   400	{
   401		return -EOPNOTSUPP;
   402	}
   403	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-09-02 14:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-02 10:50 [PATCH iwl-next 0/2] idpf: add direct access for PHC control Anton Nadezhdin
2025-09-02 10:50 ` [PATCH iwl-next 1/2] idpf: add direct access to discipline the main timer Anton Nadezhdin
2025-09-02 11:05   ` Vadim Fedorenko
2025-09-02 10:50 ` [PATCH iwl-next 2/2] idpf: add direct method for disciplining Tx timestamping Anton Nadezhdin
2025-09-02 11:27   ` Vadim Fedorenko
2025-09-02 14:06   ` [Intel-wired-lan] " kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).