[PATCH net-next 3/3] net/mlx5: Support getcyclesx and getcrosscycles

Tariq Toukan posted 3 patches 2 months, 3 weeks ago
There is a newer version of this series
[PATCH net-next 3/3] net/mlx5: Support getcyclesx and getcrosscycles
Posted by Tariq Toukan 2 months, 3 weeks ago
From: Carolina Jubran <cjubran@nvidia.com>

Implement the getcyclesx64 and getcrosscycles callbacks in ptp_info to
expose the device’s raw free-running counter.

Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
 .../ethernet/mellanox/mlx5/core/lib/clock.c   | 74 ++++++++++++++++++-
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index b1e2deeefc0c..2f75726674a9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -306,6 +306,23 @@ static int mlx5_mtctr_syncdevicetime(ktime_t *device_time,
 	return 0;
 }
 
+static int
+mlx5_mtctr_syncdevicecyclestime(ktime_t *device_time,
+				struct system_counterval_t *sys_counterval,
+				void *ctx)
+{
+	struct mlx5_core_dev *mdev = ctx;
+	u64 device;
+	int err;
+
+	err = mlx5_mtctr_read(mdev, false, sys_counterval, &device);
+	if (err)
+		return err;
+	*device_time = ns_to_ktime(device);
+
+	return 0;
+}
+
 static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp,
 				   struct system_device_crosststamp *cts)
 {
@@ -330,6 +347,32 @@ static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp,
 	mlx5_clock_unlock(clock);
 	return err;
 }
+
+static int mlx5_ptp_getcrosscycles(struct ptp_clock_info *ptp,
+				   struct system_device_crosststamp *cts)
+{
+	struct mlx5_clock *clock =
+		container_of(ptp, struct mlx5_clock, ptp_info);
+	struct system_time_snapshot history_begin = {0};
+	struct mlx5_core_dev *mdev;
+	int err;
+
+	mlx5_clock_lock(clock);
+	mdev = mlx5_clock_mdev_get(clock);
+
+	if (!mlx5_is_ptm_source_time_available(mdev)) {
+		err = -EBUSY;
+		goto unlock;
+	}
+
+	ktime_get_snapshot(&history_begin);
+
+	err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime,
+					    mdev, &history_begin, cts);
+unlock:
+	mlx5_clock_unlock(clock);
+	return err;
+}
 #endif /* CONFIG_X86 */
 
 static u64 mlx5_read_time(struct mlx5_core_dev *dev,
@@ -528,6 +571,24 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
 	return 0;
 }
 
+static int mlx5_ptp_getcyclesx(struct ptp_clock_info *ptp,
+			       struct timespec64 *ts,
+			       struct ptp_system_timestamp *sts)
+{
+	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
+						ptp_info);
+	struct mlx5_core_dev *mdev;
+	u64 cycles;
+
+	mlx5_clock_lock(clock);
+	mdev = mlx5_clock_mdev_get(clock);
+
+	cycles = mlx5_read_time(mdev, sts, false);
+	*ts = ns_to_timespec64(cycles);
+	mlx5_clock_unlock(clock);
+	return 0;
+}
+
 static int mlx5_ptp_adjtime_real_time(struct mlx5_core_dev *mdev, s64 delta)
 {
 	u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {};
@@ -1244,6 +1305,7 @@ static void mlx5_init_timer_max_freq_adjustment(struct mlx5_core_dev *mdev)
 static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev)
 {
 	struct mlx5_clock *clock = mdev->clock;
+	bool expose_cycles;
 
 	/* Configure the PHC */
 	clock->ptp_info = mlx5_ptp_clock_info;
@@ -1251,12 +1313,22 @@ static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev)
 	if (MLX5_CAP_MCAM_REG(mdev, mtutc))
 		mlx5_init_timer_max_freq_adjustment(mdev);
 
+	expose_cycles = !MLX5_CAP_GEN(mdev, disciplined_fr_counter) ||
+			!mlx5_real_time_mode(mdev);
+
 #ifdef CONFIG_X86
 	if (MLX5_CAP_MCAM_REG3(mdev, mtptm) &&
-	    MLX5_CAP_MCAM_REG3(mdev, mtctr) && boot_cpu_has(X86_FEATURE_ART))
+	    MLX5_CAP_MCAM_REG3(mdev, mtctr) && boot_cpu_has(X86_FEATURE_ART)) {
 		clock->ptp_info.getcrosststamp = mlx5_ptp_getcrosststamp;
+		if (expose_cycles)
+			clock->ptp_info.getcrosscycles =
+				mlx5_ptp_getcrosscycles;
+	}
 #endif /* CONFIG_X86 */
 
+	if (expose_cycles)
+		clock->ptp_info.getcyclesx64 = mlx5_ptp_getcyclesx;
+
 	mlx5_timecounter_init(mdev);
 	mlx5_init_clock_info(mdev);
 	mlx5_init_overflow_period(mdev);
-- 
2.31.1

Re: [PATCH net-next 3/3] net/mlx5: Support getcyclesx and getcrosscycles
Posted by Paolo Abeni 2 months, 3 weeks ago
On 7/15/25 7:15 AM, Tariq Toukan wrote:
> From: Carolina Jubran <cjubran@nvidia.com>
> 
> Implement the getcyclesx64 and getcrosscycles callbacks in ptp_info to
> expose the device’s raw free-running counter.
> 
> Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
> ---
>  .../ethernet/mellanox/mlx5/core/lib/clock.c   | 74 ++++++++++++++++++-
>  1 file changed, 73 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
> index b1e2deeefc0c..2f75726674a9 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
> @@ -306,6 +306,23 @@ static int mlx5_mtctr_syncdevicetime(ktime_t *device_time,
>  	return 0;
>  }
>  
> +static int
> +mlx5_mtctr_syncdevicecyclestime(ktime_t *device_time,
> +				struct system_counterval_t *sys_counterval,
> +				void *ctx)
> +{
> +	struct mlx5_core_dev *mdev = ctx;
> +	u64 device;
> +	int err;
> +
> +	err = mlx5_mtctr_read(mdev, false, sys_counterval, &device);
> +	if (err)
> +		return err;
> +	*device_time = ns_to_ktime(device);

If the goal is providing a raw cycle counter, why still using a timespec
to the user space? A plain u64 would possibly be less ambiguous.

/P

Re: [PATCH net-next 3/3] net/mlx5: Support getcyclesx and getcrosscycles
Posted by Carolina Jubran 2 months, 3 weeks ago

On 17/07/2025 13:55, Paolo Abeni wrote:
> On 7/15/25 7:15 AM, Tariq Toukan wrote:
>> From: Carolina Jubran <cjubran@nvidia.com>
>>
>> Implement the getcyclesx64 and getcrosscycles callbacks in ptp_info to
>> expose the device’s raw free-running counter.
>>
>> Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
>> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
>> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
>> ---
>>   .../ethernet/mellanox/mlx5/core/lib/clock.c   | 74 ++++++++++++++++++-
>>   1 file changed, 73 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
>> index b1e2deeefc0c..2f75726674a9 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
>> @@ -306,6 +306,23 @@ static int mlx5_mtctr_syncdevicetime(ktime_t *device_time,
>>   	return 0;
>>   }
>>   
>> +static int
>> +mlx5_mtctr_syncdevicecyclestime(ktime_t *device_time,
>> +				struct system_counterval_t *sys_counterval,
>> +				void *ctx)
>> +{
>> +	struct mlx5_core_dev *mdev = ctx;
>> +	u64 device;
>> +	int err;
>> +
>> +	err = mlx5_mtctr_read(mdev, false, sys_counterval, &device);
>> +	if (err)
>> +		return err;
>> +	*device_time = ns_to_ktime(device);
> 
> If the goal is providing a raw cycle counter, why still using a timespec
> to the user space? A plain u64 would possibly be less ambiguous.
> 
> /P
> 

getcycles64 and getcrosscycles already return the cycle counter in a 
timespec64/ktime format, so I kept the new ioctls consistent with them.

Re: [PATCH net-next 3/3] net/mlx5: Support getcyclesx and getcrosscycles
Posted by Paolo Abeni 2 months, 2 weeks ago
On 7/17/25 5:56 PM, Carolina Jubran wrote:
> On 17/07/2025 13:55, Paolo Abeni wrote:
>> On 7/15/25 7:15 AM, Tariq Toukan wrote:
>>> From: Carolina Jubran <cjubran@nvidia.com>
>>>
>>> Implement the getcyclesx64 and getcrosscycles callbacks in ptp_info to
>>> expose the device’s raw free-running counter.
>>>
>>> Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
>>> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
>>> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
>>> ---
>>>   .../ethernet/mellanox/mlx5/core/lib/clock.c   | 74 ++++++++++++++++++-
>>>   1 file changed, 73 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
>>> index b1e2deeefc0c..2f75726674a9 100644
>>> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
>>> @@ -306,6 +306,23 @@ static int mlx5_mtctr_syncdevicetime(ktime_t *device_time,
>>>   	return 0;
>>>   }
>>>   
>>> +static int
>>> +mlx5_mtctr_syncdevicecyclestime(ktime_t *device_time,
>>> +				struct system_counterval_t *sys_counterval,
>>> +				void *ctx)
>>> +{
>>> +	struct mlx5_core_dev *mdev = ctx;
>>> +	u64 device;
>>> +	int err;
>>> +
>>> +	err = mlx5_mtctr_read(mdev, false, sys_counterval, &device);
>>> +	if (err)
>>> +		return err;
>>> +	*device_time = ns_to_ktime(device);
>>
>> If the goal is providing a raw cycle counter, why still using a timespec
>> to the user space? A plain u64 would possibly be less ambiguous.
>>
>> /P
>>
> 
> getcycles64 and getcrosscycles already return the cycle counter in a 
> timespec64/ktime format, so I kept the new ioctls consistent with them.

Ah, sorry I missed that context. Looks good to me than.

Thanks,

Paolo