drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
Extension
.c
Size
44530 bytes
Lines
1655
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlx5_clock_dev_state {
	struct mlx5_core_dev *mdev;
	struct mlx5_devcom_comp_dev *compdev;
	struct mlx5_nb pps_nb;
	struct work_struct out_work;
};

struct mlx5_clock_priv {
	struct mlx5_clock clock;
	struct mlx5_core_dev *mdev;
	struct mutex lock; /* protect mdev and used in PTP callbacks */
	struct mlx5_core_dev *event_mdev;
};

static struct mlx5_clock_priv *clock_priv(struct mlx5_clock *clock)
{
	return container_of(clock, struct mlx5_clock_priv, clock);
}

static void mlx5_clock_lockdep_assert(struct mlx5_clock *clock)
{
	if (!clock->shared)
		return;

	lockdep_assert(lockdep_is_held(&clock_priv(clock)->lock));
}

static struct mlx5_core_dev *mlx5_clock_mdev_get(struct mlx5_clock *clock)
{
	mlx5_clock_lockdep_assert(clock);

	return clock_priv(clock)->mdev;
}

static void mlx5_clock_lock(struct mlx5_clock *clock)
{
	if (!clock->shared)
		return;

	mutex_lock(&clock_priv(clock)->lock);
}

static void mlx5_clock_unlock(struct mlx5_clock *clock)
{
	if (!clock->shared)
		return;

	mutex_unlock(&clock_priv(clock)->lock);
}

static bool mlx5_real_time_mode(struct mlx5_core_dev *mdev)
{
	return (mlx5_is_real_time_rq(mdev) || mlx5_is_real_time_sq(mdev));
}

static bool mlx5_npps_real_time_supported(struct mlx5_core_dev *mdev)
{
	return (mlx5_real_time_mode(mdev) &&
		MLX5_CAP_MCAM_FEATURE(mdev, npps_period) &&
		MLX5_CAP_MCAM_FEATURE(mdev, out_pulse_duration_ns));
}

static bool mlx5_modify_mtutc_allowed(struct mlx5_core_dev *mdev)
{
	return MLX5_CAP_MCAM_FEATURE(mdev, ptpcyc2realtime_modify);
}

static int mlx5_clock_identity_get(struct mlx5_core_dev *mdev,
				   u8 identify[MLX5_RT_CLOCK_IDENTITY_SIZE])
{
	u32 out[MLX5_ST_SZ_DW(mrtcq_reg)] = {};
	u32 in[MLX5_ST_SZ_DW(mrtcq_reg)] = {};
	int err;

	err = mlx5_core_access_reg(mdev, in, sizeof(in),
				   out, sizeof(out), MLX5_REG_MRTCQ, 0, 0);
	if (!err)
		memcpy(identify, MLX5_ADDR_OF(mrtcq_reg, out, rt_clock_identity),
		       MLX5_RT_CLOCK_IDENTITY_SIZE);

	return err;
}

static u32 mlx5_ptp_shift_constant(u32 dev_freq_khz)
{
	/* Optimal shift constant leads to corrections above just 1 scaled ppm.
	 *
	 * Two sets of equations are needed to derive the optimal shift
	 * constant for the cyclecounter.
	 *

Annotation

Implementation Notes